forked from acouzens/open5gs
NGSetup is added
This commit is contained in:
parent
c534d47a78
commit
6ef5a746e5
|
@ -0,0 +1,85 @@
|
|||
db_uri: mongodb://localhost/open5gs
|
||||
|
||||
logger:
|
||||
|
||||
parameter:
|
||||
|
||||
nrf:
|
||||
sbi:
|
||||
- addr:
|
||||
- 127.0.0.1
|
||||
- ::1
|
||||
port: 7777
|
||||
|
||||
amf:
|
||||
sbi:
|
||||
- addr: 127.0.0.2
|
||||
port: 7777
|
||||
ngap:
|
||||
guami:
|
||||
- plmn_id:
|
||||
mcc: 208
|
||||
mnc: 93
|
||||
amf_id:
|
||||
region: 202
|
||||
set: 1016
|
||||
tai:
|
||||
- plmn_id:
|
||||
mcc: 901
|
||||
mnc: 70
|
||||
tac: 1
|
||||
plmn:
|
||||
- plmn_id:
|
||||
mcc: 901
|
||||
mnc: 70
|
||||
s_nssai:
|
||||
- sst: 1
|
||||
security:
|
||||
integrity_order : [ EIA1, EIA2, EIA0 ]
|
||||
ciphering_order : [ EEA0, EEA1, EEA2 ]
|
||||
network_name:
|
||||
full: Open5GS
|
||||
amf_name: amf.open5gs.org
|
||||
|
||||
smf:
|
||||
sbi:
|
||||
- addr: 127.0.0.3
|
||||
port: 7777
|
||||
gtpc:
|
||||
- addr: 127.0.0.3
|
||||
- addr: ::1
|
||||
pfcp:
|
||||
- addr: 127.0.0.3
|
||||
pdn:
|
||||
- addr: 10.45.0.1/16
|
||||
- addr: cafe::1/64
|
||||
dns:
|
||||
- 8.8.8.8
|
||||
- 8.8.4.4
|
||||
- 2001:4860:4860::8888
|
||||
- 2001:4860:4860::8844
|
||||
mtu: 1400
|
||||
freeDiameter:
|
||||
identity: pgw.open-ims.test
|
||||
realm: open-ims.test
|
||||
listen_on: 127.0.0.3
|
||||
load_extension:
|
||||
- module: @freediameter_extensions_builddir@/dbg_msg_dumps.fdx
|
||||
conf: 0x8888
|
||||
- module: @freediameter_extensions_builddir@/dict_rfc5777.fdx
|
||||
- module: @freediameter_extensions_builddir@/dict_mip6i.fdx
|
||||
- module: @freediameter_extensions_builddir@/dict_nasreq.fdx
|
||||
- module: @freediameter_extensions_builddir@/dict_nas_mipv6.fdx
|
||||
- module: @freediameter_extensions_builddir@/dict_dcca.fdx
|
||||
- module: @freediameter_extensions_builddir@/dict_dcca_3gpp.fdx
|
||||
connect:
|
||||
- identity: pcrf.open-ims.test
|
||||
addr: 127.0.0.5
|
||||
upf:
|
||||
pfcp:
|
||||
addr: 127.0.0.4
|
||||
gtpu:
|
||||
- addr:
|
||||
- 127.0.0.4
|
||||
- ::1
|
||||
pdn:
|
|
@ -34,9 +34,11 @@ else
|
|||
endif
|
||||
|
||||
example_conf = '''
|
||||
simple.yaml
|
||||
installed.yaml
|
||||
split.yaml
|
||||
5gc.yaml
|
||||
minimal.yaml
|
||||
epc.yaml
|
||||
epc-fdconf.yaml
|
||||
epc-custom.yaml
|
||||
mnc3.yaml
|
||||
csfb.yaml
|
||||
volte.yaml
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
db_uri: mongodb://localhost/open5gs
|
||||
|
||||
logger:
|
||||
|
||||
parameter:
|
||||
|
||||
nrf:
|
||||
sbi:
|
||||
- addr:
|
||||
- 127.0.0.1
|
||||
- ::1
|
||||
port: 7777
|
||||
|
||||
amf:
|
||||
sbi:
|
||||
- addr: 127.0.0.2
|
||||
port: 7777
|
||||
ngap:
|
||||
- addr: 127.0.0.1
|
||||
guami:
|
||||
- plmn_id:
|
||||
mcc: 208
|
||||
mnc: 93
|
||||
amf_id:
|
||||
region: 202
|
||||
set: 1016
|
||||
tai:
|
||||
- plmn_id:
|
||||
mcc: 208
|
||||
mnc: 93
|
||||
tac: 1
|
||||
plmn:
|
||||
- plmn_id:
|
||||
mcc: 208
|
||||
mnc: 93
|
||||
s_nssai:
|
||||
- sst: 1
|
||||
sd: 010203
|
||||
- sst: 1
|
||||
sd: 112233
|
||||
security:
|
||||
integrity_order : [ EIA1, EIA2, EIA0 ]
|
||||
ciphering_order : [ EEA0, EEA1, EEA2 ]
|
||||
network_name:
|
||||
full: Open5GS
|
||||
amf_name: amf.open5gs.org
|
||||
|
||||
smf:
|
||||
sbi:
|
||||
- addr: 127.0.0.3
|
||||
port: 7777
|
||||
gtpc:
|
||||
- addr: 127.0.0.3
|
||||
- addr: ::1
|
||||
pfcp:
|
||||
- addr: 127.0.0.3
|
||||
pdn:
|
||||
- addr: 10.45.0.1/16
|
||||
- addr: cafe::1/64
|
||||
dns:
|
||||
- 8.8.8.8
|
||||
- 8.8.4.4
|
||||
- 2001:4860:4860::8888
|
||||
- 2001:4860:4860::8844
|
||||
mtu: 1400
|
||||
freeDiameter:
|
||||
identity: pgw.open-ims.test
|
||||
realm: open-ims.test
|
||||
listen_on: 127.0.0.3
|
||||
load_extension:
|
||||
- module: @freediameter_extensions_builddir@/dbg_msg_dumps.fdx
|
||||
conf: 0x8888
|
||||
- module: @freediameter_extensions_builddir@/dict_rfc5777.fdx
|
||||
- module: @freediameter_extensions_builddir@/dict_mip6i.fdx
|
||||
- module: @freediameter_extensions_builddir@/dict_nasreq.fdx
|
||||
- module: @freediameter_extensions_builddir@/dict_nas_mipv6.fdx
|
||||
- module: @freediameter_extensions_builddir@/dict_dcca.fdx
|
||||
- module: @freediameter_extensions_builddir@/dict_dcca_3gpp.fdx
|
||||
connect:
|
||||
- identity: pcrf.open-ims.test
|
||||
addr: 127.0.0.5
|
||||
upf:
|
||||
pfcp:
|
||||
- addr: 127.0.0.4
|
||||
gtpu:
|
||||
- addr:
|
||||
- 127.0.0.4
|
||||
- ::1
|
||||
pdn:
|
|
@ -0,0 +1,202 @@
|
|||
#
|
||||
# logger:
|
||||
#
|
||||
# o Set OGS_LOG_INFO to all domain level
|
||||
# - If `level` is omitted, the default level is OGS_LOG_INFO)
|
||||
# - If `domain` is omitted, the all domain level is set from 'level'
|
||||
# (Nothing is needed)
|
||||
#
|
||||
# o Set OGS_LOG_ERROR to all domain level
|
||||
# - `level` can be set with none, fatal, error, warn, info, debug, trace
|
||||
# level: error
|
||||
#
|
||||
# o Set OGS_LOG_DEBUG to mme/emm domain level
|
||||
# level: debug
|
||||
# domain: mme,emm
|
||||
#
|
||||
# o Set OGS_LOG_TRACE to all domain level
|
||||
# level: trace
|
||||
# domain: core,pfcp,fd,gtp,amf,event,tlv,mem,sock
|
||||
#
|
||||
logger:
|
||||
file: @localstatedir@/log/open5gs/amf.log
|
||||
#
|
||||
# amf:
|
||||
#
|
||||
# <SBI Server>
|
||||
#
|
||||
# o SBI Server(http://<all address available>:80)
|
||||
# sbi:
|
||||
#
|
||||
# o SBI Server(http://<any address>:80)
|
||||
# sbi:
|
||||
# - addr:
|
||||
# - 0.0.0.0
|
||||
# - ::0
|
||||
# port: 7777
|
||||
#
|
||||
# o SBI Server(https://<all address avaiable>:443)
|
||||
# sbi:
|
||||
# tls:
|
||||
# key: amf.key
|
||||
# pem: amf.pem
|
||||
#
|
||||
# o SBI Server(https://127.0.0.2:443, http://[::1]:80)
|
||||
# sbi:
|
||||
# - addr: 127.0.0.2
|
||||
# tls:
|
||||
# key: amf.key
|
||||
# pem: amf.pem
|
||||
# - addr: ::1
|
||||
#
|
||||
# o SBI Server(http://amf.open5gs.org:80)
|
||||
# sbi:
|
||||
# name: amf.open5gs.org
|
||||
#
|
||||
# o SBI Server(http://127.0.0.2:7777)
|
||||
# sbi:
|
||||
# - addr: 127.0.0.2
|
||||
# port: 7777
|
||||
#
|
||||
# o SBI Server(http://<eth0 IP address>:80)
|
||||
# sbi:
|
||||
# dev: eth0
|
||||
#
|
||||
amf:
|
||||
sbi:
|
||||
- addr: 127.0.0.2
|
||||
port: 7777
|
||||
ngap:
|
||||
guami:
|
||||
- plmn_id:
|
||||
mcc: 901
|
||||
mnc: 70
|
||||
amf_id:
|
||||
region: 2
|
||||
set: 1
|
||||
tai:
|
||||
- plmn_id:
|
||||
mcc: 901
|
||||
mnc: 70
|
||||
tac: 1
|
||||
plmn:
|
||||
- plmn_id:
|
||||
mcc: 901
|
||||
mnc: 70
|
||||
s_nssai:
|
||||
- sst: 1
|
||||
security:
|
||||
integrity_order : [ EIA1, EIA2, EIA0 ]
|
||||
ciphering_order : [ EEA0, EEA1, EEA2 ]
|
||||
network_name:
|
||||
full: Open5GS
|
||||
amf_name: amf.open5gs.org
|
||||
|
||||
#
|
||||
# nrf:
|
||||
#
|
||||
# <SBI Client>>
|
||||
#
|
||||
# o SBI Client(http://127.0.0.1:7777)
|
||||
# sbi:
|
||||
# addr: 127.0.0.1
|
||||
# port: 7777
|
||||
#
|
||||
# o SBI Client(https://127.0.0.1:443, http://nrf.open5gs.org:80)
|
||||
# sbi:
|
||||
# - addr: 127.0.0.1
|
||||
# tls:
|
||||
# key: nrf.key
|
||||
# pem: nrf.pem
|
||||
# - name: nrf.open5gs.org
|
||||
#
|
||||
# o SBI Client(http://[fe80::1%@loopback_devname@]:80)
|
||||
# If prefer_ipv4 is true, http://127.0.0.1:80 is selected.
|
||||
#
|
||||
# sbi:
|
||||
# addr:
|
||||
# - 127.0.0.1
|
||||
# - fe80::1%@loopback_devname@
|
||||
#
|
||||
nrf:
|
||||
sbi:
|
||||
- addr:
|
||||
- 127.0.0.1
|
||||
- ::1
|
||||
port: 7777
|
||||
|
||||
#
|
||||
# parameter:
|
||||
#
|
||||
# o Number of output streams per SCTP associations.
|
||||
# sctp_streams: 30
|
||||
#
|
||||
# o Disable use of IPv4 addresses (only IPv6)
|
||||
# no_ipv4: true
|
||||
#
|
||||
# o Disable use of IPv6 addresses (only IPv4)
|
||||
# no_ipv6: true
|
||||
#
|
||||
# o Prefer IPv4 instead of IPv6 for estabishing new GTP connections.
|
||||
# prefer_ipv4: true
|
||||
#
|
||||
# o Enable Multicast traffic to the UE
|
||||
# multicast: true
|
||||
#
|
||||
# o Disable Stateless Address Autoconfiguration for IPv6
|
||||
# no_slaac: true
|
||||
#
|
||||
parameter:
|
||||
|
||||
#
|
||||
# max:
|
||||
#
|
||||
# o Maximum Number of gNB per AMF
|
||||
# gnb: 32
|
||||
# o Maximum Number of UE per gNB
|
||||
# ue: 128
|
||||
#
|
||||
max:
|
||||
|
||||
#
|
||||
# pool:
|
||||
#
|
||||
# o The Number of Default Memory Pool Size
|
||||
#
|
||||
# - Pool-size 128 => 8192 Number
|
||||
# - Pool-size 256 => 4096 Number
|
||||
# - Pool-size 512 => 2048 Number
|
||||
# - Pool-size 1024 => 1024 Number
|
||||
# - Pool-size 2048 => 512 Number
|
||||
# - Pool-size 8192 => 128 Number
|
||||
# - Pool-size 1024*1024 => 8 Number
|
||||
#
|
||||
# 128: 8192
|
||||
# 256: 4096
|
||||
# 512: 2048
|
||||
# 1024: 1024
|
||||
# 2048: 512
|
||||
# 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
|
||||
#
|
||||
# packet: 65536
|
||||
#
|
||||
pool:
|
||||
|
||||
#
|
||||
# time:
|
||||
#
|
||||
# o NF Instance Heartbeat (Default : 3 seconds)
|
||||
#
|
||||
# o NF Instance Heartbeat (Disabled)
|
||||
# nf_instance:
|
||||
# heartbeat: 0
|
||||
#
|
||||
# o NF Instance Heartbeat (5 seconds)
|
||||
# nf_instance:
|
||||
# heartbeat: 5
|
||||
time:
|
|
@ -27,8 +27,9 @@ open5gs_conf = '''
|
|||
pcrf.yaml
|
||||
|
||||
nrf.yaml
|
||||
smf.yaml
|
||||
upf.yaml
|
||||
smf.yaml
|
||||
amf.yaml
|
||||
'''.split()
|
||||
|
||||
foreach file : open5gs_conf
|
||||
|
|
|
@ -98,15 +98,9 @@ parameter:
|
|||
#
|
||||
# max:
|
||||
#
|
||||
# o Maximum Number of SGW per MME
|
||||
# sgw: 32
|
||||
# o Maximum Number of PGW per MME
|
||||
# pgw: 32
|
||||
# o Maximum Number of VLR per MME
|
||||
# vlr: 32
|
||||
# o Maximum Number of eNodeB per MME
|
||||
# enb: 32
|
||||
# o Maximum Number of UE per eNodeB
|
||||
# o Maximum Number of gNB per MME
|
||||
# gnb: 32
|
||||
# o Maximum Number of UE per gNB
|
||||
# ue: 128
|
||||
#
|
||||
max:
|
||||
|
|
|
@ -228,7 +228,7 @@ smf:
|
|||
#
|
||||
nrf:
|
||||
sbi:
|
||||
addr:
|
||||
- addr:
|
||||
- 127.0.0.1
|
||||
- ::1
|
||||
port: 7777
|
||||
|
@ -245,7 +245,7 @@ nrf:
|
|||
#
|
||||
upf:
|
||||
pfcp:
|
||||
addr: 127.0.0.4
|
||||
- addr: 127.0.0.4
|
||||
|
||||
#
|
||||
# parameter:
|
||||
|
@ -273,15 +273,9 @@ parameter:
|
|||
#
|
||||
# max:
|
||||
#
|
||||
# o Maximum Number of SGW per MME
|
||||
# sgw: 32
|
||||
# o Maximum Number of PGW per MME
|
||||
# pgw: 32
|
||||
# o Maximum Number of VLR per MME
|
||||
# vlr: 32
|
||||
# o Maximum Number of eNodeB per MME
|
||||
# enb: 32
|
||||
# o Maximum Number of UE per eNodeB
|
||||
# o Maximum Number of gNB per AMF
|
||||
# gnb: 32
|
||||
# o Maximum Number of UE per gNB
|
||||
# ue: 128
|
||||
#
|
||||
max:
|
||||
|
|
|
@ -59,7 +59,7 @@ logger:
|
|||
#
|
||||
upf:
|
||||
pfcp:
|
||||
addr: 127.0.0.4
|
||||
- addr: 127.0.0.4
|
||||
gtpu:
|
||||
- addr:
|
||||
- 127.0.0.4
|
||||
|
@ -78,7 +78,7 @@ upf:
|
|||
#
|
||||
smf:
|
||||
pfcp:
|
||||
addr: 127.0.0.3
|
||||
- addr: 127.0.0.3
|
||||
|
||||
#
|
||||
# parameter:
|
||||
|
@ -107,15 +107,9 @@ parameter:
|
|||
#
|
||||
# max:
|
||||
#
|
||||
# o Maximum Number of SGW per MME
|
||||
# sgw: 32
|
||||
# o Maximum Number of PGW per MME
|
||||
# pgw: 32
|
||||
# o Maximum Number of VLR per MME
|
||||
# vlr: 32
|
||||
# o Maximum Number of eNodeB per MME
|
||||
# enb: 32
|
||||
# o Maximum Number of UE per eNodeB
|
||||
# o Maximum Number of gNB per AMF
|
||||
# gnb: 32
|
||||
# o Maximum Number of UE per gNB
|
||||
# ue: 128
|
||||
#
|
||||
max:
|
||||
|
|
|
@ -11,10 +11,10 @@ Sometimes you may get a message like the one below due to a problem with the fre
|
|||
$ meson test
|
||||
|
||||
...
|
||||
5/8 open5gs:system / simple OK 7.69 s
|
||||
5/8 open5gs:epc / simple OK 7.69 s
|
||||
|
||||
--- command ---
|
||||
08:06:23 /home/parallels/open5gs/build/tests/simple/simple
|
||||
08:06:23 /home/parallels/open5gs/build/tests/epc-simple/simple
|
||||
--- stdout ---
|
||||
s1setup-test : SUCCESS
|
||||
attach-test : SUCCESS
|
||||
|
@ -123,10 +123,10 @@ ninja: no work to do.
|
|||
2/8 open5gs:unit / crypt OK 0.08 s
|
||||
3/8 open5gs:system / sctp OK 1.09 s
|
||||
4/8 open5gs:unit / unit OK 0.04 s
|
||||
5/8 open5gs:system / simple OK 5.07 s
|
||||
6/8 open5gs:system / mnc3 OK 1.18 s
|
||||
7/8 open5gs:system / volte OK 2.99 s
|
||||
8/8 open5gs:system / csfb OK 6.53 s
|
||||
5/8 open5gs:epc / simple OK 5.07 s
|
||||
6/8 open5gs:epc / mnc3 OK 1.18 s
|
||||
7/8 open5gs:epc / volte OK 2.99 s
|
||||
8/8 open5gs:epc / csfb OK 6.53 s
|
||||
|
||||
Ok: 8
|
||||
Expected Fail: 0
|
||||
|
@ -385,17 +385,17 @@ You can start MongoDB using systemctl.
|
|||
$ sudo systemctl start mongodb
|
||||
```
|
||||
|
||||
#### I have some error when running `./build/test/simple/simple`
|
||||
#### I have some error when running `./build/test/epc-simple/simple`
|
||||
|
||||
Did you see the following error after executing `./build/test/simple/simple`?
|
||||
Did you see the following error after executing `./build/test/epc-simple/simple`?
|
||||
```bash
|
||||
$ ./build/test/simple/simple
|
||||
$ ./build/test/epc-simple/simple
|
||||
s1setup_test : SUCCESS
|
||||
attach_test : -Line 134: Condition is false, but expected true
|
||||
\04/09 15:49:09.285: [esm] FATAL: esm_handle_pdn_connectivity_request: Assertion `SECURITY_CONTEXT_IS_VALID(mme_ue)' failed. (esm_handler.c:29)
|
||||
/home/acetcom/Documents/git/open5gs/open5gs/lib/ogslib/src/core/.libs/libogscore-1.0.so.0(ogs_abort+0x2b)[0x7f608518271b]
|
||||
/home/acetcom/Documents/git/open5gs/open5gs/test/.libs/testcomplex(+0x92121)[0x55dc9e274121]
|
||||
/home/acetcom/Documents/git/open5gs/open5gs/test/.libs/testcomplex(+0x4f5b9)[0x55dc9e2315b9]
|
||||
/home/acetcom/Documents/git/open5gs/open5gs/test/.libs/simple(+0x92121)[0x55dc9e274121]
|
||||
/home/acetcom/Documents/git/open5gs/open5gs/test/.libs/simple(+0x4f5b9)[0x55dc9e2315b9]
|
||||
```
|
||||
|
||||
|
||||
|
@ -415,9 +415,9 @@ $ sudo pkill -9 simple
|
|||
$ sudo pkill -9 open5gs-mmed ...
|
||||
```
|
||||
|
||||
Execute `./build/test/simple/simple`
|
||||
Execute `./build/test/epc-simple/simple`
|
||||
```bash
|
||||
$ ./build/test/simple/simple
|
||||
$ ./build/test/epc-simple/simple
|
||||
```
|
||||
|
||||
#### My eNB does not support IPv6.
|
||||
|
|
|
@ -60,11 +60,14 @@ void pcrf_terminate(void);
|
|||
int nrf_initialize(void);
|
||||
void nrf_terminate(void);
|
||||
|
||||
int upf_initialize(void);
|
||||
void upf_terminate(void);
|
||||
|
||||
int smf_initialize(void);
|
||||
void smf_terminate(void);
|
||||
|
||||
int upf_initialize(void);
|
||||
void upf_terminate(void);
|
||||
int amf_initialize(void);
|
||||
void amf_terminate(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ static void recalculate_pool_size(void)
|
|||
#define MAX_NUM_OF_TUNNEL 3 /* Num of Tunnel per Bearer */
|
||||
#define MAX_NUM_OF_PF 16 /* Num of PacketFilter per Bearer */
|
||||
|
||||
self.pool.ue = self.max.ue * self.max.enb;
|
||||
self.pool.ue = self.max.ue * self.max.gnb;
|
||||
self.pool.pfcp = ogs_max(self.max.smf, self.max.upf);
|
||||
self.pool.sbi = self.pool.pfcp;
|
||||
self.pool.sess = self.pool.ue * OGS_MAX_NUM_OF_SESS;
|
||||
|
@ -156,15 +156,17 @@ static int config_prepare(void)
|
|||
#define MAX_NUM_OF_PGW 32 /* Num of PGW per MME */
|
||||
#define MAX_NUM_OF_VLR 32 /* Num of VLR per MME */
|
||||
#define MAX_NUM_OF_CSMAP 128 /* Num of TAI-LAI MAP per MME */
|
||||
#define MAX_NUM_OF_ENB 32 /* Num of eNodeB per MME */
|
||||
#define MAX_NUM_OF_UE 128 /* Num of UE per eNodeB */
|
||||
|
||||
#define MAX_NUM_OF_UE 128 /* Num of UE per gNB */
|
||||
#define MAX_NUM_OF_SMF 32 /* Num of SMF per AMF */
|
||||
#define MAX_NUM_OF_UPF 32 /* Num of PGW per AMF */
|
||||
#define MAX_NUM_OF_GNB 32 /* Num of gNB per AMF */
|
||||
self.max.sgw = MAX_NUM_OF_SGW;
|
||||
self.max.pgw = MAX_NUM_OF_PGW;
|
||||
self.max.vlr = MAX_NUM_OF_VLR;
|
||||
self.max.csmap = MAX_NUM_OF_CSMAP;
|
||||
self.max.enb = MAX_NUM_OF_ENB;
|
||||
|
||||
self.max.gnb = MAX_NUM_OF_GNB;
|
||||
self.max.ue = MAX_NUM_OF_UE;
|
||||
self.max.smf = MAX_NUM_OF_SMF;
|
||||
self.max.upf = MAX_NUM_OF_UPF;
|
||||
|
@ -323,9 +325,10 @@ int ogs_config_parse()
|
|||
if (!strcmp(max_key, "ue")) {
|
||||
const char *v = ogs_yaml_iter_value(&max_iter);
|
||||
if (v) self.max.ue = atoi(v);
|
||||
} else if (!strcmp(max_key, "enb")) {
|
||||
} else if (!strcmp(max_key, "gnb") ||
|
||||
!strcmp(max_key, "enb")) {
|
||||
const char *v = ogs_yaml_iter_value(&max_iter);
|
||||
if (v) self.max.enb = atoi(v);
|
||||
if (v) self.max.gnb = atoi(v);
|
||||
} else
|
||||
ogs_warn("unknown key `%s`", max_key);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,11 @@ typedef struct ogs_config_s {
|
|||
int no_pgw;
|
||||
int no_pcrf;
|
||||
|
||||
int no_amf;
|
||||
int no_smf;
|
||||
int no_upf;
|
||||
int no_nrf;
|
||||
|
||||
/* Network */
|
||||
int no_ipv4;
|
||||
int no_ipv6;
|
||||
|
@ -66,10 +71,11 @@ typedef struct ogs_config_s {
|
|||
int pgw;
|
||||
int vlr;
|
||||
int csmap;
|
||||
int enb;
|
||||
|
||||
int ue;
|
||||
int smf;
|
||||
int upf;
|
||||
int gnb;
|
||||
} max;
|
||||
|
||||
struct {
|
||||
|
|
|
@ -38,6 +38,17 @@ void ogs_asn_uint16_to_OCTET_STRING(
|
|||
octet_string->buf[1] = uint16;
|
||||
}
|
||||
|
||||
void ogs_asn_uint24_to_OCTET_STRING(
|
||||
ogs_uint24_t uint24, OCTET_STRING_t *octet_string)
|
||||
{
|
||||
octet_string->size = 3;
|
||||
octet_string->buf = CALLOC(octet_string->size, sizeof(uint8_t));
|
||||
|
||||
octet_string->buf[0] = uint24.v >> 16;
|
||||
octet_string->buf[1] = uint24.v >> 8;
|
||||
octet_string->buf[2] = uint24.v;
|
||||
}
|
||||
|
||||
void ogs_asn_uint32_to_OCTET_STRING(
|
||||
uint32_t uint32, OCTET_STRING_t *octet_string)
|
||||
{
|
||||
|
@ -50,6 +61,15 @@ void ogs_asn_uint32_to_OCTET_STRING(
|
|||
octet_string->buf[3] = uint32;
|
||||
}
|
||||
|
||||
void ogs_asn_buffer_to_OCTET_STRING(
|
||||
void *buf, int size, OCTET_STRING_t *octet_string)
|
||||
{
|
||||
octet_string->size = size;
|
||||
octet_string->buf = CALLOC(octet_string->size, sizeof(uint8_t));
|
||||
|
||||
memcpy(octet_string->buf, buf, size);
|
||||
}
|
||||
|
||||
int ogs_asn_BIT_STRING_to_ip(BIT_STRING_t *bit_string, ogs_ip_t *ip)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN], buf2[OGS_ADDRSTRLEN];
|
||||
|
|
|
@ -30,12 +30,36 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define OGS_ASN_CLEAR_DATA(__dATA) \
|
||||
do { \
|
||||
ogs_assert((__dATA)); \
|
||||
if ((__dATA)->buf) { \
|
||||
FREEMEM((__dATA)->buf); \
|
||||
(__dATA)->buf = NULL; \
|
||||
(__dATA)->size = 0; \
|
||||
} \
|
||||
} while(0)
|
||||
#define OGS_ASN_STORE_DATA(__dST, __sRC) \
|
||||
do { \
|
||||
ogs_assert((__sRC)); \
|
||||
ogs_assert((__sRC)->buf); \
|
||||
ogs_assert((__dST)); \
|
||||
OGS_ASN_CLEAR_DATA(__dST); \
|
||||
(__dST)->size = (__sRC)->size; \
|
||||
(__dST)->buf = CALLOC((__dST)->size, sizeof(uint8_t)); \
|
||||
memcpy((__dST)->buf, (__sRC)->buf, (__dST)->size); \
|
||||
} while(0)
|
||||
|
||||
void ogs_asn_uint8_to_OCTET_STRING(
|
||||
uint8_t uint8, OCTET_STRING_t *octet_string);
|
||||
void ogs_asn_uint16_to_OCTET_STRING(
|
||||
uint16_t uint16, OCTET_STRING_t *octet_string);
|
||||
void ogs_asn_uint24_to_OCTET_STRING(
|
||||
ogs_uint24_t uint24, OCTET_STRING_t *octet_string);
|
||||
void ogs_asn_uint32_to_OCTET_STRING(
|
||||
uint32_t uint32, OCTET_STRING_t *octet_string);
|
||||
void ogs_asn_buffer_to_OCTET_STRING(
|
||||
void *buf, int size, OCTET_STRING_t *octet_string);
|
||||
|
||||
int ogs_asn_BIT_STRING_to_ip(
|
||||
BIT_STRING_t *bit_string, ogs_ip_t *ip);
|
||||
|
|
|
@ -64,6 +64,82 @@ void *ogs_plmn_id_build(ogs_plmn_id_t *plmn_id,
|
|||
return plmn_id;
|
||||
}
|
||||
|
||||
uint32_t ogs_amf_id_hexdump(ogs_amf_id_t *amf_id)
|
||||
{
|
||||
uint32_t hex;
|
||||
|
||||
ogs_assert(amf_id);
|
||||
|
||||
memcpy(&hex, amf_id, sizeof(ogs_amf_id_t));
|
||||
hex = be32toh(hex) >> 8;
|
||||
|
||||
return hex;
|
||||
}
|
||||
|
||||
ogs_amf_id_t *ogs_amf_id_from_string(ogs_amf_id_t *amf_id, const char *hex)
|
||||
{
|
||||
char hexbuf[sizeof(ogs_amf_id_t)];
|
||||
|
||||
ogs_assert(amf_id);
|
||||
ogs_assert(hex);
|
||||
|
||||
OGS_HEX(hex, strlen(hex), hexbuf);
|
||||
|
||||
amf_id->region = hexbuf[0];
|
||||
amf_id->set1 = hexbuf[1];
|
||||
amf_id->set2 = (hexbuf[2] & 0xc0) >> 6;
|
||||
amf_id->pointer = hexbuf[2] & 0x3f;
|
||||
|
||||
return amf_id;
|
||||
}
|
||||
|
||||
char *ogs_amf_id_to_string(ogs_amf_id_t *amf_id, char *buf)
|
||||
{
|
||||
int i;
|
||||
ogs_assert(amf_id);
|
||||
ogs_assert(buf);
|
||||
|
||||
ogs_hex_to_ascii(amf_id, sizeof(ogs_amf_id_t), buf, OGS_AMFIDSTRLEN);
|
||||
|
||||
/* I'd just like to use lower character */
|
||||
for (i = 0; buf[i]; i++)
|
||||
if (buf[i] >= 'A' && buf[i] <= 'Z')
|
||||
buf[i] = buf[i] + 'a' - 'A';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
uint8_t ogs_amf_region_id(ogs_amf_id_t *amf_id)
|
||||
{
|
||||
ogs_assert(amf_id);
|
||||
return amf_id->region;
|
||||
}
|
||||
uint16_t ogs_amf_set_id(ogs_amf_id_t *amf_id)
|
||||
{
|
||||
ogs_assert(amf_id);
|
||||
return (amf_id->set1 << 2) + amf_id->set2;
|
||||
}
|
||||
uint8_t ogs_amf_pointer(ogs_amf_id_t *amf_id)
|
||||
{
|
||||
ogs_assert(amf_id);
|
||||
return amf_id->pointer;
|
||||
}
|
||||
|
||||
ogs_amf_id_t *ogs_amf_id_build(ogs_amf_id_t *amf_id,
|
||||
uint8_t region, uint16_t set, uint8_t pointer)
|
||||
{
|
||||
ogs_assert(amf_id);
|
||||
ogs_assert(region);
|
||||
ogs_assert(set);
|
||||
|
||||
amf_id->region = region;
|
||||
amf_id->set1 = set >> 2;
|
||||
amf_id->set2 = set & 0x3;
|
||||
amf_id->pointer = pointer;
|
||||
|
||||
return amf_id;
|
||||
}
|
||||
|
||||
int ogs_fqdn_build(char *dst, char *src, int length)
|
||||
{
|
||||
int i = 0, j = 0;
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#define OGS_MAX_FILEPATH_LEN 256
|
||||
|
||||
#define OGS_MAX_NUM_OF_SESS 4 /* Num of APN(Session) per UE */
|
||||
#define OGS_MAX_NUM_OF_RULE 4 /* Num of Rule per Session */
|
||||
|
||||
|
@ -50,7 +48,11 @@ extern "C" {
|
|||
#define OGS_MAX_DNN_LEN 100
|
||||
#define OGS_MAX_PCO_LEN 251
|
||||
#define OGS_MAX_FQDN_LEN 256
|
||||
#define OGS_MAX_IFNAME_LEN 32
|
||||
|
||||
#define OGS_MAX_NUM_OF_SERVED_TAI 16
|
||||
#define OGS_MAX_NUM_OF_ALGORITHM 8
|
||||
|
||||
#define OGS_MAX_NUM_OF_BPLMN 6
|
||||
|
||||
#define OGS_NEXT_ID(__id, __min, __max) \
|
||||
((__id) = ((__id) == (__max) ? (__min) : ((__id) + 1)))
|
||||
|
@ -63,8 +65,49 @@ extern "C" {
|
|||
|
||||
#define OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED 0
|
||||
|
||||
/**********************************
|
||||
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
|
||||
typedef struct ogs_plmn_id_s {
|
||||
ED2(uint8_t mcc2:4;,
|
||||
uint8_t mcc1:4;)
|
||||
|
@ -83,18 +126,55 @@ uint16_t ogs_plmn_id_mnc_len(ogs_plmn_id_t *plmn_id);
|
|||
void *ogs_plmn_id_build(ogs_plmn_id_t *plmn_id,
|
||||
uint16_t mcc, uint16_t mnc, uint16_t mnc_len);
|
||||
|
||||
#define OGS_MAX_NUM_OF_TAI 16
|
||||
/************************************
|
||||
* AMF_ID Structure */
|
||||
typedef struct ogs_amf_id_s {
|
||||
uint8_t region;
|
||||
uint8_t set1;
|
||||
ED2(uint8_t set2:2;,
|
||||
uint8_t pointer:6;)
|
||||
} __attribute__ ((packed)) ogs_amf_id_t;
|
||||
|
||||
typedef struct ogs_tai_s {
|
||||
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);
|
||||
|
||||
uint8_t ogs_amf_region_id(ogs_amf_id_t *amf_id);
|
||||
uint16_t ogs_amf_set_id(ogs_amf_id_t *amf_id);
|
||||
uint8_t ogs_amf_pointer(ogs_amf_id_t *amf_id);
|
||||
|
||||
ogs_amf_id_t *ogs_amf_id_build(ogs_amf_id_t *amf_id,
|
||||
uint8_t region, uint16_t set, uint8_t pointer);
|
||||
|
||||
/************************************
|
||||
* TAI Structure */
|
||||
#define OGS_MAX_NUM_OF_TAI 16
|
||||
typedef struct ogs_eps_tai_s {
|
||||
ogs_plmn_id_t plmn_id;
|
||||
uint16_t tac;
|
||||
} __attribute__ ((packed)) ogs_tai_t;
|
||||
} __attribute__ ((packed)) ogs_eps_tai_t;
|
||||
|
||||
typedef struct ogs_5gs_tai_s {
|
||||
ogs_plmn_id_t plmn_id;
|
||||
ogs_uint24_t tac;
|
||||
} __attribute__ ((packed)) ogs_5gs_tai_t;
|
||||
|
||||
typedef struct ogs_e_cgi_s {
|
||||
ogs_plmn_id_t plmn_id;
|
||||
uint32_t cell_id; /* 28 bit */
|
||||
} __attribute__ ((packed)) ogs_e_cgi_t;
|
||||
|
||||
/************************************
|
||||
* S-NSSAI Structure */
|
||||
#define OGS_MAX_NUM_OF_S_NSSAI 8
|
||||
#define OGS_S_NSSAI_NO_SD_VALUE 0xffffff
|
||||
typedef struct ogs_s_nssai_s {
|
||||
uint8_t sst;
|
||||
ogs_uint24_t sd;
|
||||
} __attribute__ ((packed)) ogs_s_nssai_t;
|
||||
|
||||
/**************************************************
|
||||
* Common Structure
|
||||
* S1AP : 9.2.2.1 Transport Layer Address, See 36.414
|
||||
|
|
|
@ -177,6 +177,10 @@ extern "C" {
|
|||
#define END }}}
|
||||
#endif
|
||||
|
||||
#define OGS_ARG_MAX 256
|
||||
#define OGS_MAX_FILEPATH_LEN 256
|
||||
#define OGS_MAX_IFNAME_LEN 32
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -344,7 +344,7 @@ typedef struct ogs_gtp_uli_s {
|
|||
ogs_gtp_uli_cgi_t cgi;
|
||||
ogs_gtp_uli_sai_t sai;
|
||||
ogs_gtp_uli_rai_t rai;
|
||||
ogs_tai_t tai;
|
||||
ogs_eps_tai_t tai;
|
||||
ogs_e_cgi_t e_cgi;
|
||||
ogs_gtp_uli_lai_t lai;
|
||||
} ogs_gtp_uli_t;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
/*******************************************************************************
|
||||
* This file had been created by nas-message.py script v0.2.0
|
||||
* Please do not modify this file but regenerate it via script.
|
||||
* Created on: 2020-05-22 16:56:22.013388 by acetcom
|
||||
* Created on: 2020-05-24 17:29:31.606634 by acetcom
|
||||
* from 24501-g41.docx
|
||||
******************************************************************************/
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
/*******************************************************************************
|
||||
* This file had been created by nas-message.py script v0.2.0
|
||||
* Please do not modify this file but regenerate it via script.
|
||||
* Created on: 2020-05-22 16:56:22.024260 by acetcom
|
||||
* Created on: 2020-05-24 17:29:31.617845 by acetcom
|
||||
* from 24501-g41.docx
|
||||
******************************************************************************/
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
/*******************************************************************************
|
||||
* This file had been created by nas-message.py script v0.2.0
|
||||
* Please do not modify this file but regenerate it via script.
|
||||
* Created on: 2020-05-22 16:56:21.995840 by acetcom
|
||||
* Created on: 2020-05-24 17:29:31.588956 by acetcom
|
||||
* from 24501-g41.docx
|
||||
******************************************************************************/
|
||||
|
||||
|
@ -2713,7 +2713,7 @@ int ogs_nas_5gs_decode_5gs_tracking_area_identity(ogs_nas_5gs_tracking_area_iden
|
|||
ogs_assert(ogs_pkbuf_pull(pkbuf, size));
|
||||
memcpy(tracking_area_identity, pkbuf->data - size, size);
|
||||
|
||||
tracking_area_identity->tac = be16toh(tracking_area_identity->tac);
|
||||
tracking_area_identity->tac = ogs_be24toh(tracking_area_identity->tac);
|
||||
|
||||
ogs_trace(" 5GS_TRACKING_AREA_IDENTITY - ");
|
||||
ogs_log_hexdump(OGS_LOG_TRACE, pkbuf->data - size, size);
|
||||
|
@ -2727,7 +2727,7 @@ int ogs_nas_5gs_encode_5gs_tracking_area_identity(ogs_pkbuf_t *pkbuf, ogs_nas_5g
|
|||
ogs_nas_5gs_tracking_area_identity_t target;
|
||||
|
||||
memcpy(&target, tracking_area_identity, size);
|
||||
target.tac = htobe16(tracking_area_identity->tac);
|
||||
target.tac = ogs_htobe24(tracking_area_identity->tac);
|
||||
|
||||
ogs_assert(ogs_pkbuf_pull(pkbuf, size));
|
||||
memcpy(pkbuf->data - size, &target, size);
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
/*******************************************************************************
|
||||
* This file had been created by nas-message.py script v0.2.0
|
||||
* Please do not modify this file but regenerate it via script.
|
||||
* Created on: 2020-05-22 16:56:21.993076 by acetcom
|
||||
* Created on: 2020-05-24 17:29:31.586197 by acetcom
|
||||
* from 24501-g41.docx
|
||||
******************************************************************************/
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
libnas_5gs_sources = files('''
|
||||
types.c
|
||||
ies.c
|
||||
decoder.c
|
||||
encoder.c
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
/*******************************************************************************
|
||||
* This file had been created by nas-message.py script v0.2.0
|
||||
* Please do not modify this file but regenerate it via script.
|
||||
* Created on: 2020-05-22 16:56:22.005526 by acetcom
|
||||
* Created on: 2020-05-24 17:29:31.598549 by acetcom
|
||||
* from 24501-g41.docx
|
||||
******************************************************************************/
|
||||
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
type_list["5GS tracking area identity"]["decode"] = \
|
||||
" tracking_area_identity->tac = be16toh(tracking_area_identity->tac);\n\n"
|
||||
" tracking_area_identity->tac = ogs_be24toh(tracking_area_identity->tac);\n\n"
|
||||
type_list["5GS tracking area identity"]["encode"] = \
|
||||
" target.tac = htobe16(tracking_area_identity->tac);\n\n"
|
||||
" target.tac = ogs_htobe24(tracking_area_identity->tac);\n\n"
|
||||
|
||||
type_list["5GS mobile identity"]["decode"] = \
|
||||
" if (mobile_identity->guti.type == OGS_NAS_5GS_MOBILE_IDENTITY_GUTI) {\n" \
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ogs-nas-5gs.h"
|
||||
|
||||
void ogs_nas_5gs_tai_list_build(
|
||||
ogs_nas_5gs_tracking_area_identity_list_t *target,
|
||||
ogs_5gs_tai0_list_t *source0, ogs_5gs_tai2_list_t *source2)
|
||||
{
|
||||
int i = 0, j = 0, size = 0;
|
||||
|
||||
ogs_5gs_tai0_list_t target0;
|
||||
ogs_5gs_tai2_list_t target2;
|
||||
ogs_nas_plmn_id_t ogs_nas_plmn_id;
|
||||
|
||||
ogs_assert(target);
|
||||
ogs_assert(source0);
|
||||
ogs_assert(source2);
|
||||
|
||||
memset(target, 0, sizeof(ogs_nas_5gs_tracking_area_identity_list_t));
|
||||
memset(&target0, 0, sizeof(ogs_5gs_tai0_list_t));
|
||||
memset(&target2, 0, sizeof(ogs_5gs_tai2_list_t));
|
||||
|
||||
for (i = 0; source0->tai[i].num; i++) {
|
||||
ogs_assert(source0->tai[i].type == OGS_TAI0_TYPE);
|
||||
target0.tai[i].type = source0->tai[i].type;
|
||||
|
||||
/* <Spec> target->num = source->num - 1 */
|
||||
ogs_assert(source0->tai[i].num < OGS_MAX_NUM_OF_TAI);
|
||||
target0.tai[i].num = source0->tai[i].num - 1;
|
||||
memcpy(&target0.tai[i].plmn_id,
|
||||
ogs_nas_from_plmn_id(&ogs_nas_plmn_id, &source0->tai[i].plmn_id),
|
||||
OGS_PLMN_ID_LEN);
|
||||
|
||||
for (j = 0; j < source0->tai[i].num; j++) {
|
||||
target0.tai[i].tac[j] = ogs_htobe24(source0->tai[i].tac[j]);
|
||||
}
|
||||
|
||||
size = (1 + 3 + 2 * source0->tai[i].num);
|
||||
if ((target->length + size) > OGS_NAS_5GS_MAX_TAI_LIST_LEN) {
|
||||
ogs_warn("Overflow: Ignore remained TAI LIST(length:%d, size:%d)",
|
||||
target->length, size);
|
||||
return;
|
||||
}
|
||||
memcpy(target->buffer + target->length, &target0.tai[i], size);
|
||||
target->length += size;
|
||||
}
|
||||
|
||||
if (source2->num) {
|
||||
memset(&target2, 0, sizeof(target2));
|
||||
|
||||
ogs_assert(source2->type == OGS_TAI1_TYPE ||
|
||||
source2->type == OGS_TAI2_TYPE);
|
||||
target2.type = source2->type;
|
||||
|
||||
/* <Spec> target->num = source->num - 1 */
|
||||
ogs_assert(source2->num < OGS_MAX_NUM_OF_TAI);
|
||||
target2.num = source2->num - 1;
|
||||
|
||||
size = (1 + (3 + 2) * source2->num);
|
||||
if ((target->length + size) > OGS_NAS_5GS_MAX_TAI_LIST_LEN) {
|
||||
ogs_warn("Overflow: Ignore remained TAI LIST(length:%d, size:%d)",
|
||||
target->length, size);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < source2->num; i++) {
|
||||
memcpy(&target2.tai[i].plmn_id,
|
||||
ogs_nas_from_plmn_id(&ogs_nas_plmn_id,
|
||||
&source2->tai[i].plmn_id),
|
||||
OGS_PLMN_ID_LEN);
|
||||
target2.tai[i].tac = ogs_htobe24(source2->tai[i].tac);
|
||||
}
|
||||
memcpy(target->buffer + target->length, &target2, size);
|
||||
target->length += size;
|
||||
}
|
||||
}
|
|
@ -28,6 +28,14 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* NAS GUTI Structure */
|
||||
typedef struct ogs_nas_5gs_guti_s {
|
||||
ogs_nas_plmn_id_t nas_plmn_id;
|
||||
ogs_amf_id_t amf_id;
|
||||
uint32_t m_tmsi;
|
||||
} __attribute__ ((packed)) ogs_nas_5gs_guti_t;
|
||||
|
||||
/* 9.11.2.1A DNN
|
||||
* O TLV 3-102 */
|
||||
typedef struct ogs_nas_dnn_s {
|
||||
|
@ -48,11 +56,10 @@ typedef struct ogs_nas_eap_message_s {
|
|||
#define OGS_NAS_S_NSSAI_SST_AND_MAPPED_HPLMN_SST_LEN 2
|
||||
#define OGS_NAS_S_NSSAI_SST_AND_SD 4
|
||||
#define OGS_NAS_S_NSSAI_SST_SD_AND_MAPPED_HPLMN_SST_LEN 5
|
||||
#define OGS_NAS_MAX_S_NSSAI_LEN 8
|
||||
typedef struct ogs_nas_s_nssai_s {
|
||||
uint8_t length;
|
||||
uint32_t sst_sd;
|
||||
uint32_t mapped_sst_sd;
|
||||
ogs_s_nssai_t s_nssai;
|
||||
ogs_s_nssai_t mapped_s_nssai;
|
||||
} __attribute__ ((packed)) ogs_nas_s_nssai_t;
|
||||
|
||||
/* 9.11.3.1 5GMM capability
|
||||
|
@ -133,20 +140,12 @@ ED3(uint8_t type:4;,
|
|||
|
||||
/* 9.11.3.4 5GS mobile identity
|
||||
* M LV-E 6-n */
|
||||
#define OGS_NAS_GET_AMF_SET_ID(_iDentity) \
|
||||
((_iDentity)->amf_set_id2 + ((_iDentity)->amf_set_id1 << 2))
|
||||
#define OGS_NAS_SET_AMF_SET_ID(_iDentity, _aMFSetId) \
|
||||
do { \
|
||||
ogs_assert((_iDentity)); \
|
||||
(_iDentity)->amf_set_id1 = (_aMFSetId >> 2) & 0x000f; \
|
||||
(_iDentity)->amf_set_id2 = _aMFSetId & 0x0003; \
|
||||
} while(0)
|
||||
typedef struct ogs_nas_5gs_mobile_identity_guti_s {
|
||||
ED3(uint8_t _0xf:4;,
|
||||
uint8_t spare:1;,
|
||||
uint8_t type:3;)
|
||||
ogs_nas_plmn_id_t nas_plmn_id;
|
||||
uint16_t amf_region_id;
|
||||
uint8_t amf_region_id;
|
||||
uint8_t amf_set_id1;
|
||||
ED2(uint8_t amf_set_id2:2;,
|
||||
uint8_t amf_pointer:6;)
|
||||
|
@ -156,7 +155,7 @@ typedef struct ogs_nas_5gs_mobile_identity_s_tmsi_s {
|
|||
ED3(uint8_t _0xf:4;,
|
||||
uint8_t spare:1;,
|
||||
uint8_t type:3;)
|
||||
uint16_t amf_region_id;
|
||||
uint8_t amf_region_id;
|
||||
uint8_t amf_set_id1;
|
||||
ED2(uint8_t amf_set_id2:2;,
|
||||
uint8_t amf_pointer:6;)
|
||||
|
@ -214,11 +213,54 @@ ED3(uint8_t type:4;,
|
|||
|
||||
/* 9.11.3.8 5GS tracking area identity
|
||||
* O TV 6 */
|
||||
typedef ogs_nas_tracking_area_identity_t ogs_nas_5gs_tracking_area_identity_t;
|
||||
typedef struct ogs_nas_5gs_tracking_area_identity_s {
|
||||
ogs_nas_plmn_id_t nas_plmn_id;
|
||||
ogs_uint24_t tac;
|
||||
} __attribute__ ((packed)) ogs_nas_5gs_tracking_area_identity_t;
|
||||
|
||||
typedef ogs_nas_5gs_tracking_area_identity_t ogs_nas_5gs_tai_t;
|
||||
|
||||
/* 9.11.3.9 5GS tracking area identity list
|
||||
* O TLV 9-114 */
|
||||
typedef ogs_nas_tracking_area_identity_list_t ogs_nas_5gs_tracking_area_identity_list_t;
|
||||
#define OGS_NAS_5GS_MAX_TAI_LIST_LEN 114
|
||||
typedef struct ogs_5gs_tai0_list_s {
|
||||
struct {
|
||||
ED3(uint8_t spare:1;,
|
||||
uint8_t type:2;,
|
||||
uint8_t num:5;)
|
||||
/*
|
||||
* Do not change 'ogs_plmn_id_t' to 'ogs_nas_plmn_id_t'.
|
||||
* Use 'ogs_plmn_id_t' for easy implementation.
|
||||
* ogs_nas_tai_list_build() changes to NAS format(ogs_nas_plmn_id_t)
|
||||
* and is sent to the UE.
|
||||
*/
|
||||
ogs_plmn_id_t plmn_id;
|
||||
ogs_uint24_t tac[OGS_MAX_NUM_OF_TAI];
|
||||
} __attribute__ ((packed)) tai[OGS_MAX_NUM_OF_TAI];
|
||||
} __attribute__ ((packed)) ogs_5gs_tai0_list_t;
|
||||
|
||||
typedef struct ogs_5gs_tai2_list_s {
|
||||
ED3(uint8_t spare:1;,
|
||||
uint8_t type:2;,
|
||||
uint8_t num:5;)
|
||||
/*
|
||||
* Do not change 'ogs_5gs_tai_t' to 'ogs_nas_tracking_area_identity_t'.
|
||||
* Use 'ogs_5gs_tai_t' for easy implementation.
|
||||
* ogs_nas_tai_list_build() changes to NAS
|
||||
* format(ogs_nas_tracking_area_identity_t)
|
||||
* and is sent to the UE.
|
||||
*/
|
||||
ogs_5gs_tai_t tai[OGS_MAX_NUM_OF_TAI];
|
||||
} __attribute__ ((packed)) ogs_5gs_tai2_list_t;
|
||||
|
||||
typedef struct ogs_nas_5gs_tracking_area_identity_list_s {
|
||||
uint8_t length;
|
||||
uint8_t buffer[OGS_NAS_5GS_MAX_TAI_LIST_LEN];
|
||||
} __attribute__ ((packed)) ogs_nas_5gs_tracking_area_identity_list_t;
|
||||
|
||||
void ogs_nas_5gs_tai_list_build(
|
||||
ogs_nas_5gs_tracking_area_identity_list_t *target,
|
||||
ogs_5gs_tai0_list_t *source0, ogs_5gs_tai2_list_t *source2);
|
||||
|
||||
/* 9.11.3.9A 5GS update type
|
||||
* O TLV 3 */
|
||||
|
@ -381,10 +423,10 @@ ED2(uint8_t type:4;,
|
|||
|
||||
/* 9.11.3.31B Mapped NSSAI
|
||||
* O TLV 3-42 */
|
||||
#define OGS_NAS_MAX_MAPPED_NSSAI_LEN 40
|
||||
#define OGS_NAX_MAX_NUM_OF_MAPPED_S_NSSAI 10
|
||||
typedef struct ogs_nas_mapped_nssai_s {
|
||||
uint8_t length;
|
||||
uint8_t buffer[OGS_NAS_MAX_MAPPED_NSSAI_LEN];
|
||||
ogs_s_nssai_t s_nssai[OGS_NAX_MAX_NUM_OF_MAPPED_S_NSSAI];
|
||||
} ogs_nas_mapped_nssai_t;
|
||||
|
||||
/* 9.11.3.33 message container
|
||||
|
@ -405,10 +447,10 @@ ED4(uint8_t type:4;,
|
|||
|
||||
/* 9.11.3.37 NSSAI
|
||||
* O TLV 4-72 */
|
||||
#define MAX_NAS_NSSAI_LEN 72
|
||||
#define OGS_NAS_MAX_NUM_OF_S_NSSAI 18
|
||||
typedef struct ogs_nas_nssai_s {
|
||||
uint8_t length;
|
||||
uint8_t buffer[MAX_NAS_NSSAI_LEN];
|
||||
ogs_s_nssai_t s_nssai[OGS_NAS_MAX_NUM_OF_S_NSSAI];
|
||||
} __attribute__ ((packed)) ogs_nas_nssai_t;
|
||||
|
||||
/* 9.11.3.37A NSSAI inclusion mode
|
||||
|
@ -468,10 +510,13 @@ typedef ogs_nas_allowed_pdu_session_status_t ogs_nas_pdu_session_status_t;
|
|||
|
||||
/* 9.11.3.46 Rejected NSSAI
|
||||
* O TLV 4-42 */
|
||||
#define OGS_MAX_NAS_REJECTED_NSSAI_LEN 40
|
||||
typedef struct ogs_nas_rejected_nssai_s {
|
||||
uint8_t length;
|
||||
uint8_t buffer[OGS_MAX_NAS_REJECTED_NSSAI_LEN];
|
||||
struct {
|
||||
ED2(uint8_t len:4;,
|
||||
uint8_t value:4;)
|
||||
ogs_s_nssai_t s_nssai;
|
||||
} rejected[OGS_MAX_NUM_OF_S_NSSAI];
|
||||
} ogs_nas_rejected_nssai_t;
|
||||
|
||||
/* 9.11.3.49 Service area list
|
||||
|
|
|
@ -427,73 +427,3 @@ void eps_qos_build(ogs_nas_eps_quality_of_service_t *eps_qos, uint8_t qci,
|
|||
|
||||
eps_qos->length = length*4+1;
|
||||
}
|
||||
|
||||
void ogs_nas_tai_list_build(
|
||||
ogs_nas_tracking_area_identity_list_t *target,
|
||||
tai0_list_t *source0, tai2_list_t *source2)
|
||||
{
|
||||
int i = 0, j = 0, size = 0;
|
||||
|
||||
tai0_list_t target0;
|
||||
tai2_list_t target2;
|
||||
ogs_nas_plmn_id_t ogs_nas_plmn_id;
|
||||
|
||||
ogs_assert(target);
|
||||
ogs_assert(source0);
|
||||
ogs_assert(source2);
|
||||
|
||||
memset(target, 0, sizeof(ogs_nas_tracking_area_identity_list_t));
|
||||
memset(&target0, 0, sizeof(tai0_list_t));
|
||||
memset(&target2, 0, sizeof(tai2_list_t));
|
||||
|
||||
for (i = 0; source0->tai[i].num; i++) {
|
||||
ogs_assert(source0->tai[i].type == TAI0_TYPE);
|
||||
target0.tai[i].type = source0->tai[i].type;
|
||||
|
||||
/* <Spec> target->num = source->num - 1 */
|
||||
ogs_assert(source0->tai[i].num < OGS_MAX_NUM_OF_TAI);
|
||||
target0.tai[i].num = source0->tai[i].num - 1;
|
||||
memcpy(&target0.tai[i].plmn_id,
|
||||
ogs_nas_from_plmn_id(&ogs_nas_plmn_id, &source0->tai[i].plmn_id),
|
||||
OGS_PLMN_ID_LEN);
|
||||
|
||||
for (j = 0; j < source0->tai[i].num; j++) {
|
||||
target0.tai[i].tac[j] = htobe16(source0->tai[i].tac[j]);
|
||||
}
|
||||
|
||||
size = (1 + 3 + 2 * source0->tai[i].num);
|
||||
if ((target->length + size) > OGS_NAS_MAX_TAI_LIST_LEN) {
|
||||
ogs_warn("Overflow: Ignore remained TAI LIST(length:%d, size:%d)",
|
||||
target->length, size);
|
||||
return;
|
||||
}
|
||||
memcpy(target->buffer + target->length, &target0.tai[i], size);
|
||||
target->length += size;
|
||||
}
|
||||
|
||||
if (source2->num) {
|
||||
memset(&target2, 0, sizeof(target2));
|
||||
|
||||
ogs_assert(source2->type == TAI1_TYPE || source2->type == TAI2_TYPE);
|
||||
target2.type = source2->type;
|
||||
|
||||
/* <Spec> target->num = source->num - 1 */
|
||||
ogs_assert(source2->num < OGS_MAX_NUM_OF_TAI);
|
||||
target2.num = source2->num - 1;
|
||||
|
||||
size = (1 + (3 + 2) * source2->num);
|
||||
if ((target->length + size) > OGS_NAS_MAX_TAI_LIST_LEN) {
|
||||
ogs_warn("Overflow: Ignore remained TAI LIST(length:%d, size:%d)",
|
||||
target->length, size);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < source2->num; i++) {
|
||||
memcpy(&target2.tai[i].plmn_id,
|
||||
ogs_nas_from_plmn_id(&ogs_nas_plmn_id, &source2->tai[i].plmn_id),
|
||||
OGS_PLMN_ID_LEN);
|
||||
target2.tai[i].tac = htobe16(source2->tai[i].tac);
|
||||
}
|
||||
memcpy(target->buffer + target->length, &target2, size);
|
||||
target->length += size;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,13 +97,6 @@ void *ogs_nas_from_plmn_id(
|
|||
void *ogs_nas_to_plmn_id(
|
||||
ogs_plmn_id_t *plmn_id, ogs_nas_plmn_id_t *ogs_nas_plmn_id);
|
||||
|
||||
typedef struct ogs_nas_guti_s {
|
||||
ogs_nas_plmn_id_t nas_plmn_id;
|
||||
uint16_t mme_gid;
|
||||
uint8_t mme_code;
|
||||
uint32_t m_tmsi;
|
||||
} __attribute__ ((packed)) ogs_nas_guti_t;
|
||||
|
||||
/* 9.9.2.0 Additional information
|
||||
* O TLV 3-n */
|
||||
#define NAX_MAX_ADDITIONAL_INFORMATION_LEN 255
|
||||
|
@ -466,59 +459,13 @@ typedef struct ogs_nas_time_zone_and_time_s {
|
|||
uint8_t timezone;
|
||||
} ogs_nas_time_zone_and_time_t;
|
||||
|
||||
/* 9.9.3.32 Tracking area identity
|
||||
* O TV 6 */
|
||||
typedef struct ogs_nas_tracking_area_identity_s {
|
||||
ogs_nas_plmn_id_t nas_plmn_id;
|
||||
uint16_t tac;
|
||||
} __attribute__ ((packed)) ogs_nas_tracking_area_identity_t;
|
||||
|
||||
typedef ogs_nas_tracking_area_identity_t ogs_nas_tai_t;
|
||||
|
||||
/* 9.9.3.33 Tracking area identity list
|
||||
* M LV 7-97 */
|
||||
#define OGS_NAS_MAX_TAI_LIST_LEN 96
|
||||
#define TAI0_TYPE 0
|
||||
#define TAI1_TYPE 1
|
||||
#define TAI2_TYPE 2
|
||||
typedef struct tai0_list_s {
|
||||
struct {
|
||||
ED3(uint8_t spare:1;,
|
||||
uint8_t type:2;,
|
||||
uint8_t num:5;)
|
||||
/*
|
||||
* Do not change 'ogs_plmn_id_t' to 'ogs_nas_plmn_id_t'.
|
||||
* Use 'ogs_plmn_id_t' for easy implementation.
|
||||
* ogs_nas_tai_list_build() changes to NAS format(ogs_nas_plmn_id_t)
|
||||
* and is sent to the UE.
|
||||
*/
|
||||
ogs_plmn_id_t plmn_id;
|
||||
uint16_t tac[OGS_MAX_NUM_OF_TAI];
|
||||
} __attribute__ ((packed)) tai[OGS_MAX_NUM_OF_TAI];
|
||||
} __attribute__ ((packed)) tai0_list_t;
|
||||
|
||||
typedef struct tai2_list_s {
|
||||
ED3(uint8_t spare:1;,
|
||||
uint8_t type:2;,
|
||||
uint8_t num:5;)
|
||||
/*
|
||||
* Do not change 'ogs_tai_t' to 'ogs_nas_tracking_area_identity_t'.
|
||||
* Use 'ogs_tai_t' for easy implementation.
|
||||
* ogs_nas_tai_list_build() changes to NAS
|
||||
* format(ogs_nas_tracking_area_identity_t)
|
||||
* and is sent to the UE.
|
||||
*/
|
||||
ogs_tai_t tai[OGS_MAX_NUM_OF_TAI];
|
||||
} __attribute__ ((packed)) tai2_list_t;
|
||||
|
||||
typedef struct ogs_nas_tracking_area_identity_list_s {
|
||||
uint8_t length;
|
||||
uint8_t buffer[OGS_NAS_MAX_TAI_LIST_LEN];
|
||||
} __attribute__ ((packed)) ogs_nas_tracking_area_identity_list_t;
|
||||
|
||||
void ogs_nas_tai_list_build(
|
||||
ogs_nas_tracking_area_identity_list_t *target,
|
||||
tai0_list_t *source0, tai2_list_t *source2);
|
||||
* M LV 7-97
|
||||
* 9.11.3.9 5GS tracking area identity list
|
||||
* O TLV 9-114 */
|
||||
#define OGS_TAI0_TYPE 0
|
||||
#define OGS_TAI1_TYPE 1
|
||||
#define OGS_TAI2_TYPE 2
|
||||
|
||||
/* 9.9.3.34 UE network capability
|
||||
* M LV 3-14
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
libnas_eps_sources = files('''
|
||||
types.c
|
||||
ies.c
|
||||
decoder.c
|
||||
encoder.c
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ogs-nas-eps.h"
|
||||
|
||||
void ogs_nas_tai_list_build(ogs_nas_tracking_area_identity_list_t *target,
|
||||
ogs_eps_tai0_list_t *source0, ogs_eps_tai2_list_t *source2)
|
||||
{
|
||||
int i = 0, j = 0, size = 0;
|
||||
|
||||
ogs_eps_tai0_list_t target0;
|
||||
ogs_eps_tai2_list_t target2;
|
||||
ogs_nas_plmn_id_t ogs_nas_plmn_id;
|
||||
|
||||
ogs_assert(target);
|
||||
ogs_assert(source0);
|
||||
ogs_assert(source2);
|
||||
|
||||
memset(target, 0, sizeof(ogs_nas_tracking_area_identity_list_t));
|
||||
memset(&target0, 0, sizeof(ogs_eps_tai0_list_t));
|
||||
memset(&target2, 0, sizeof(ogs_eps_tai2_list_t));
|
||||
|
||||
for (i = 0; source0->tai[i].num; i++) {
|
||||
ogs_assert(source0->tai[i].type == OGS_TAI0_TYPE);
|
||||
target0.tai[i].type = source0->tai[i].type;
|
||||
|
||||
/* <Spec> target->num = source->num - 1 */
|
||||
ogs_assert(source0->tai[i].num < OGS_MAX_NUM_OF_TAI);
|
||||
target0.tai[i].num = source0->tai[i].num - 1;
|
||||
memcpy(&target0.tai[i].plmn_id,
|
||||
ogs_nas_from_plmn_id(&ogs_nas_plmn_id, &source0->tai[i].plmn_id),
|
||||
OGS_PLMN_ID_LEN);
|
||||
|
||||
for (j = 0; j < source0->tai[i].num; j++) {
|
||||
target0.tai[i].tac[j] = htobe16(source0->tai[i].tac[j]);
|
||||
}
|
||||
|
||||
size = (1 + 3 + 2 * source0->tai[i].num);
|
||||
if ((target->length + size) > OGS_NAS_EPS_MAX_TAI_LIST_LEN) {
|
||||
ogs_warn("Overflow: Ignore remained TAI LIST(length:%d, size:%d)",
|
||||
target->length, size);
|
||||
return;
|
||||
}
|
||||
memcpy(target->buffer + target->length, &target0.tai[i], size);
|
||||
target->length += size;
|
||||
}
|
||||
|
||||
if (source2->num) {
|
||||
memset(&target2, 0, sizeof(target2));
|
||||
|
||||
ogs_assert(source2->type == OGS_TAI1_TYPE ||
|
||||
source2->type == OGS_TAI2_TYPE);
|
||||
target2.type = source2->type;
|
||||
|
||||
/* <Spec> target->num = source->num - 1 */
|
||||
ogs_assert(source2->num < OGS_MAX_NUM_OF_TAI);
|
||||
target2.num = source2->num - 1;
|
||||
|
||||
size = (1 + (3 + 2) * source2->num);
|
||||
if ((target->length + size) > OGS_NAS_EPS_MAX_TAI_LIST_LEN) {
|
||||
ogs_warn("Overflow: Ignore remained TAI LIST(length:%d, size:%d)",
|
||||
target->length, size);
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < source2->num; i++) {
|
||||
memcpy(&target2.tai[i].plmn_id,
|
||||
ogs_nas_from_plmn_id(&ogs_nas_plmn_id,
|
||||
&source2->tai[i].plmn_id),
|
||||
OGS_PLMN_ID_LEN);
|
||||
target2.tai[i].tac = htobe16(source2->tai[i].tac);
|
||||
}
|
||||
memcpy(target->buffer + target->length, &target2, size);
|
||||
target->length += size;
|
||||
}
|
||||
}
|
|
@ -28,6 +28,15 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* NAS GUTI Structure */
|
||||
typedef struct ogs_nas_eps_guti_s {
|
||||
ogs_nas_plmn_id_t nas_plmn_id;
|
||||
uint16_t mme_gid;
|
||||
uint8_t mme_code;
|
||||
uint32_t m_tmsi;
|
||||
} __attribute__ ((packed)) ogs_nas_eps_guti_t;
|
||||
|
||||
/* 9.9.2.0A Device properties
|
||||
* See subclause 10.5.7.8 in 3GPP TS 24.008 [13].
|
||||
* O TV 1 */
|
||||
|
@ -418,6 +427,57 @@ ED3(uint8_t type:4;,
|
|||
uint8_t tmsi_flag:1;)
|
||||
} __attribute__ ((packed)) ogs_nas_tmsi_status_t;
|
||||
|
||||
/* 9.9.3.32 Tracking area identity
|
||||
* O TV 6 */
|
||||
typedef struct ogs_nas_tracking_area_identity_s {
|
||||
ogs_nas_plmn_id_t nas_plmn_id;
|
||||
uint16_t tac;
|
||||
} __attribute__ ((packed)) ogs_nas_tracking_area_identity_t;
|
||||
|
||||
typedef ogs_nas_tracking_area_identity_t ogs_nas_eps_tai_t;
|
||||
|
||||
/* 9.9.3.33 Tracking area identity list
|
||||
* M LV 7-97 */
|
||||
#define OGS_NAS_EPS_MAX_TAI_LIST_LEN 96
|
||||
typedef struct ogs_eps_tai0_list_s {
|
||||
struct {
|
||||
ED3(uint8_t spare:1;,
|
||||
uint8_t type:2;,
|
||||
uint8_t num:5;)
|
||||
/*
|
||||
* Do not change 'ogs_plmn_id_t' to 'ogs_nas_plmn_id_t'.
|
||||
* Use 'ogs_plmn_id_t' for easy implementation.
|
||||
* ogs_nas_tai_list_build() changes to NAS format(ogs_nas_plmn_id_t)
|
||||
* and is sent to the UE.
|
||||
*/
|
||||
ogs_plmn_id_t plmn_id;
|
||||
uint16_t tac[OGS_MAX_NUM_OF_TAI];
|
||||
} __attribute__ ((packed)) tai[OGS_MAX_NUM_OF_TAI];
|
||||
} __attribute__ ((packed)) ogs_eps_tai0_list_t;
|
||||
|
||||
typedef struct ogs_eps_tai2_list_s {
|
||||
ED3(uint8_t spare:1;,
|
||||
uint8_t type:2;,
|
||||
uint8_t num:5;)
|
||||
/*
|
||||
* Do not change 'ogs_eps_tai_t' to 'ogs_nas_tracking_area_identity_t'.
|
||||
* Use 'ogs_eps_tai_t' for easy implementation.
|
||||
* ogs_nas_tai_list_build() changes to NAS
|
||||
* format(ogs_nas_tracking_area_identity_t)
|
||||
* and is sent to the UE.
|
||||
*/
|
||||
ogs_eps_tai_t tai[OGS_MAX_NUM_OF_TAI];
|
||||
} __attribute__ ((packed)) ogs_eps_tai2_list_t;
|
||||
|
||||
typedef struct ogs_nas_tracking_area_identity_list_s {
|
||||
uint8_t length;
|
||||
uint8_t buffer[OGS_NAS_EPS_MAX_TAI_LIST_LEN];
|
||||
} __attribute__ ((packed)) ogs_nas_tracking_area_identity_list_t;
|
||||
|
||||
void ogs_nas_tai_list_build(ogs_nas_tracking_area_identity_list_t *target,
|
||||
ogs_eps_tai0_list_t *source0, ogs_eps_tai2_list_t *source2);
|
||||
|
||||
|
||||
/* 9.9.3.35 UE radio capability information update needed
|
||||
* O TV 1 */
|
||||
typedef struct ogs_nas_ue_radio_capability_information_update_needed_s {
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ogs-ngap.h"
|
||||
|
||||
void ogs_ngap_uint32_to_GNB_ID(uint32_t gnb_id, NGAP_GNB_ID_t *gNB_ID)
|
||||
{
|
||||
BIT_STRING_t *bit_string = NULL;
|
||||
|
||||
ogs_assert(gNB_ID);
|
||||
|
||||
bit_string = &gNB_ID->choice.gNB_ID;
|
||||
ogs_assert(bit_string);
|
||||
|
||||
gNB_ID->present = NGAP_GNB_ID_PR_gNB_ID;
|
||||
bit_string->size = 3;
|
||||
bit_string->buf = CALLOC(bit_string->size, sizeof(uint8_t));
|
||||
|
||||
bit_string->buf[0] = gnb_id >> 16;
|
||||
bit_string->buf[1] = gnb_id >> 8;
|
||||
bit_string->buf[2] = (gnb_id & 0xff);
|
||||
}
|
||||
|
||||
void ogs_ngap_GNB_ID_to_uint32(NGAP_GNB_ID_t *gNB_ID, uint32_t *gnb_id)
|
||||
{
|
||||
uint8_t *buf = NULL;
|
||||
|
||||
ogs_assert(gnb_id);
|
||||
ogs_assert(gNB_ID);
|
||||
|
||||
buf = gNB_ID->choice.gNB_ID.buf;
|
||||
ogs_assert(buf);
|
||||
|
||||
*gnb_id = (buf[0] << 16) + (buf[1] << 8) + buf[2];
|
||||
}
|
||||
|
||||
void ogs_ngap_uint8_to_AMFRegionID(
|
||||
uint8_t region, NGAP_AMFRegionID_t *aMFRegionID)
|
||||
{
|
||||
ogs_assert(aMFRegionID);
|
||||
|
||||
aMFRegionID->size = 1;
|
||||
aMFRegionID->buf = CALLOC(aMFRegionID->size, sizeof(uint8_t));
|
||||
|
||||
aMFRegionID->buf[0] = region;
|
||||
}
|
||||
void ogs_ngap_uint16_to_NGAP_AMFSetID(
|
||||
uint16_t set, NGAP_AMFSetID_t *aMFSetID)
|
||||
{
|
||||
ogs_assert(aMFSetID);
|
||||
|
||||
aMFSetID->size = 2;
|
||||
aMFSetID->buf = CALLOC(aMFSetID->size, sizeof(uint8_t));
|
||||
aMFSetID->bits_unused = 6;
|
||||
|
||||
aMFSetID->buf[0] = (set >> 2);
|
||||
aMFSetID->buf[1] = ((set & 0x03) << 6);
|
||||
}
|
||||
void ogs_ngap_uint8_to_NGAP_NGAP_AMFPointer(
|
||||
uint8_t pointer, NGAP_AMFPointer_t *aMFPointer)
|
||||
{
|
||||
ogs_assert(aMFPointer);
|
||||
|
||||
aMFPointer->size = 1;
|
||||
aMFPointer->buf = CALLOC(aMFPointer->size, sizeof(uint8_t));
|
||||
aMFPointer->bits_unused = 2;
|
||||
|
||||
aMFPointer->buf[0] = (pointer << 2);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(OGS_NGAP_INSIDE) && !defined(OGS_NGAP_COMPILATION)
|
||||
#error "This header cannot be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef OGS_NGAP_CONV_H
|
||||
#define OGS_NGAP_CONV_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ogs_ngap_uint32_to_GNB_ID(uint32_t gnb_id, NGAP_GNB_ID_t *gNB_ID);
|
||||
void ogs_ngap_GNB_ID_to_uint32(NGAP_GNB_ID_t *gNB_ID, uint32_t *gnb_id);
|
||||
|
||||
void ogs_ngap_uint8_to_AMFRegionID(
|
||||
uint8_t region, NGAP_AMFRegionID_t *aMFRegionID);
|
||||
void ogs_ngap_uint16_to_NGAP_AMFSetID(
|
||||
uint16_t set, NGAP_AMFSetID_t *aMFSetID);
|
||||
void ogs_ngap_uint8_to_NGAP_NGAP_AMFPointer(
|
||||
uint8_t pointer, NGAP_AMFPointer_t *aMFPointer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OGS_NGAP_CONV_H */
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
# Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
|
||||
# This file is part of Open5GS.
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
libngap_sources = files('''
|
||||
conv.c
|
||||
message.c
|
||||
'''.split())
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
|
@ -28,27 +28,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Octets */
|
||||
#define OGS_NGAP_CLEAR_DATA(__dATA) \
|
||||
do { \
|
||||
ogs_assert((__dATA)); \
|
||||
if ((__dATA)->buf) { \
|
||||
FREEMEM((__dATA)->buf); \
|
||||
(__dATA)->buf = NULL; \
|
||||
(__dATA)->size = 0; \
|
||||
} \
|
||||
} while(0)
|
||||
#define OGS_NGAP_STORE_DATA(__dST, __sRC) \
|
||||
do { \
|
||||
ogs_assert((__sRC)); \
|
||||
ogs_assert((__sRC)->buf); \
|
||||
ogs_assert((__dST)); \
|
||||
OGS_NGAP_CLEAR_DATA(__dST); \
|
||||
(__dST)->size = (__sRC)->size; \
|
||||
(__dST)->buf = CALLOC((__dST)->size, sizeof(uint8_t)); \
|
||||
memcpy((__dST)->buf, (__sRC)->buf, (__dST)->size); \
|
||||
} while(0)
|
||||
|
||||
typedef struct NGAP_NGAP_PDU ogs_ngap_message_t;
|
||||
|
||||
int ogs_ngap_decode(ogs_ngap_message_t *message, ogs_pkbuf_t *pkbuf);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
|
@ -633,6 +633,7 @@
|
|||
|
||||
#define OGS_NGAP_INSIDE
|
||||
|
||||
#include "ngap/conv.h"
|
||||
#include "ngap/message.h"
|
||||
|
||||
#undef OGS_NGAP_INSIDE
|
||||
|
|
|
@ -28,27 +28,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Octets */
|
||||
#define OGS_S1AP_CLEAR_DATA(__dATA) \
|
||||
do { \
|
||||
ogs_assert((__dATA)); \
|
||||
if ((__dATA)->buf) { \
|
||||
FREEMEM((__dATA)->buf); \
|
||||
(__dATA)->buf = NULL; \
|
||||
(__dATA)->size = 0; \
|
||||
} \
|
||||
} while(0)
|
||||
#define OGS_S1AP_STORE_DATA(__dST, __sRC) \
|
||||
do { \
|
||||
ogs_assert((__sRC)); \
|
||||
ogs_assert((__sRC)->buf); \
|
||||
ogs_assert((__dST)); \
|
||||
OGS_S1AP_CLEAR_DATA(__dST); \
|
||||
(__dST)->size = (__sRC)->size; \
|
||||
(__dST)->buf = CALLOC((__dST)->size, sizeof(uint8_t)); \
|
||||
memcpy((__dST)->buf, (__sRC)->buf, (__dST)->size); \
|
||||
} while(0)
|
||||
|
||||
typedef struct S1AP_S1AP_PDU ogs_s1ap_message_t;
|
||||
|
||||
int ogs_s1ap_decode(ogs_s1ap_message_t *message, ogs_pkbuf_t *pkbuf);
|
||||
|
|
|
@ -41,10 +41,12 @@ extern int __ogs_sctp_domain;
|
|||
|
||||
#define OGS_S1AP_SCTP_PORT 36412
|
||||
#define OGS_SGSAP_SCTP_PORT 29118
|
||||
#define OGS_NGAP_SCTP_PORT 38412
|
||||
|
||||
#define OGS_SCTP_S1AP_PPID 18
|
||||
#define OGS_SCTP_X2AP_PPID 27
|
||||
#define OGS_SCTP_SGSAP_PPID 0
|
||||
#define OGS_SCTP_NGAP_PPID 60
|
||||
|
||||
#if HAVE_USRSCTP
|
||||
|
||||
|
|
|
@ -0,0 +1,415 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "sbi-path.h"
|
||||
#include "nnrf-handler.h"
|
||||
#include "ngap-path.h"
|
||||
|
||||
void amf_state_initial(ogs_fsm_t *s, amf_event_t *e)
|
||||
{
|
||||
amf_sm_debug(e);
|
||||
|
||||
ogs_assert(s);
|
||||
|
||||
OGS_FSM_TRAN(s, &amf_state_operational);
|
||||
}
|
||||
|
||||
void amf_state_final(ogs_fsm_t *s, amf_event_t *e)
|
||||
{
|
||||
amf_sm_debug(e);
|
||||
|
||||
ogs_assert(s);
|
||||
}
|
||||
|
||||
void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
|
||||
{
|
||||
int rv;
|
||||
#if 0
|
||||
ogs_pkbuf_t *recvbuf = NULL;
|
||||
#endif
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
|
||||
ogs_sock_t *sock = NULL;
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
amf_gnb_t *gnb = NULL;
|
||||
uint16_t max_num_of_ostreams = 0;
|
||||
|
||||
ogs_ngap_message_t ngap_message;
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
int rc;
|
||||
|
||||
#if 0
|
||||
ogs_nas_5gs_message_t nas_message;
|
||||
#endif
|
||||
|
||||
ogs_sbi_server_t *server = NULL;
|
||||
ogs_sbi_session_t *session = NULL;
|
||||
ogs_sbi_request_t *sbi_request = NULL;
|
||||
|
||||
ogs_sbi_nf_instance_t *nf_instance = NULL;
|
||||
ogs_sbi_subscription_t *subscription = NULL;
|
||||
ogs_sbi_response_t *sbi_response = NULL;
|
||||
ogs_sbi_message_t sbi_message;
|
||||
|
||||
amf_sm_debug(e);
|
||||
|
||||
ogs_assert(s);
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
rv = amf_sbi_open();
|
||||
if (rv != OGS_OK) {
|
||||
ogs_fatal("Can't establish SBI path");
|
||||
}
|
||||
|
||||
rv = ngap_open();
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("Can't establish NGAP path");
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case OGS_FSM_EXIT_SIG:
|
||||
ngap_close();
|
||||
amf_sbi_close();
|
||||
break;
|
||||
|
||||
case AMF_EVT_SBI_SERVER:
|
||||
sbi_request = e->sbi.request;
|
||||
ogs_assert(sbi_request);
|
||||
session = e->sbi.session;
|
||||
ogs_assert(session);
|
||||
server = e->sbi.server;
|
||||
ogs_assert(server);
|
||||
|
||||
rv = ogs_sbi_parse_request(&sbi_message, sbi_request);
|
||||
if (rv != OGS_OK) {
|
||||
/* 'sbi_message' buffer is released in ogs_sbi_parse_request() */
|
||||
ogs_error("cannot parse HTTP sbi_message");
|
||||
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
NULL, "cannot parse HTTP sbi_message", NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
if (strcmp(sbi_message.h.api.version, OGS_SBI_API_VERSION) != 0) {
|
||||
ogs_error("Not supported version [%s]", sbi_message.h.api.version);
|
||||
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
&sbi_message, "Not supported version", NULL);
|
||||
ogs_sbi_message_free(&sbi_message);
|
||||
break;
|
||||
}
|
||||
|
||||
SWITCH(sbi_message.h.service.name)
|
||||
CASE(OGS_SBI_SERVICE_NAME_NRF_NFM)
|
||||
|
||||
SWITCH(sbi_message.h.resource.name)
|
||||
CASE(OGS_SBI_RESOURCE_NAME_NF_STATUS_NOTIFY)
|
||||
SWITCH(sbi_message.h.method)
|
||||
CASE(OGS_SBI_HTTP_METHOD_POST)
|
||||
amf_nnrf_handle_nf_status_notify(
|
||||
server, session, &sbi_message);
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
ogs_error("Invalid HTTP method [%s]",
|
||||
sbi_message.h.method);
|
||||
ogs_sbi_server_send_error(session,
|
||||
OGS_SBI_HTTP_STATUS_MEHTOD_NOT_ALLOWED,
|
||||
&sbi_message,
|
||||
"Invalid HTTP method", sbi_message.h.method);
|
||||
END
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
ogs_error("Invalid resource name [%s]",
|
||||
sbi_message.h.resource.name);
|
||||
ogs_sbi_server_send_error(session,
|
||||
OGS_SBI_HTTP_STATUS_MEHTOD_NOT_ALLOWED, &sbi_message,
|
||||
"Unknown resource name", sbi_message.h.resource.name);
|
||||
END
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
ogs_error("Invalid API name [%s]", sbi_message.h.service.name);
|
||||
ogs_sbi_server_send_error(session,
|
||||
OGS_SBI_HTTP_STATUS_MEHTOD_NOT_ALLOWED, &sbi_message,
|
||||
"Invalid API name", sbi_message.h.resource.name);
|
||||
END
|
||||
|
||||
/* In lib/sbi/server.c, notify_completed() releases 'request' buffer. */
|
||||
ogs_sbi_message_free(&sbi_message);
|
||||
break;
|
||||
|
||||
case AMF_EVT_SBI_CLIENT:
|
||||
ogs_assert(e);
|
||||
|
||||
sbi_response = e->sbi.response;
|
||||
ogs_assert(sbi_response);
|
||||
rv = ogs_sbi_parse_response(&sbi_message, sbi_response);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("cannot parse HTTP response");
|
||||
ogs_sbi_message_free(&sbi_message);
|
||||
ogs_sbi_response_free(sbi_response);
|
||||
break;
|
||||
}
|
||||
|
||||
if (strcmp(sbi_message.h.api.version, OGS_SBI_API_VERSION) != 0) {
|
||||
ogs_error("Not supported version [%s]", sbi_message.h.api.version);
|
||||
ogs_sbi_message_free(&sbi_message);
|
||||
ogs_sbi_response_free(sbi_response);
|
||||
break;
|
||||
}
|
||||
|
||||
SWITCH(sbi_message.h.service.name)
|
||||
CASE(OGS_SBI_SERVICE_NAME_NRF_NFM)
|
||||
|
||||
SWITCH(sbi_message.h.resource.name)
|
||||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||
nf_instance = e->sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
|
||||
|
||||
e->sbi.message = &sbi_message;
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
|
||||
if (OGS_FSM_CHECK(&nf_instance->sm, amf_nf_state_exception)) {
|
||||
ogs_error("State machine exception");
|
||||
}
|
||||
break;
|
||||
|
||||
CASE(OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS)
|
||||
subscription = e->sbi.data;
|
||||
ogs_assert(subscription);
|
||||
|
||||
SWITCH(sbi_message.h.method)
|
||||
CASE(OGS_SBI_HTTP_METHOD_POST)
|
||||
if (sbi_message.res_status == OGS_SBI_HTTP_STATUS_CREATED ||
|
||||
sbi_message.res_status == OGS_SBI_HTTP_STATUS_OK) {
|
||||
amf_nnrf_handle_nf_status_subscribe(
|
||||
subscription, &sbi_message);
|
||||
} else {
|
||||
ogs_error("HTTP response error : %d",
|
||||
sbi_message.res_status);
|
||||
}
|
||||
break;
|
||||
|
||||
CASE(OGS_SBI_HTTP_METHOD_DELETE)
|
||||
if (sbi_message.res_status ==
|
||||
OGS_SBI_HTTP_STATUS_NO_CONTENT) {
|
||||
ogs_sbi_subscription_remove(subscription);
|
||||
} else {
|
||||
ogs_error("HTTP response error : %d",
|
||||
sbi_message.res_status);
|
||||
}
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
ogs_error("Invalid HTTP method [%s]", sbi_message.h.method);
|
||||
END
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
ogs_error("Invalid resource name [%s]",
|
||||
sbi_message.h.resource.name);
|
||||
END
|
||||
break;
|
||||
|
||||
CASE(OGS_SBI_SERVICE_NAME_NRF_DISC)
|
||||
SWITCH(sbi_message.h.resource.name)
|
||||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||
if (sbi_message.res_status == OGS_SBI_HTTP_STATUS_OK) {
|
||||
amf_nnrf_handle_nf_discover(&sbi_message);
|
||||
} else {
|
||||
ogs_error("HTTP response error : %d",
|
||||
sbi_message.res_status);
|
||||
}
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
ogs_error("Invalid resource name [%s]",
|
||||
sbi_message.h.resource.name);
|
||||
END
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
ogs_error("Invalid API name [%s]", sbi_message.h.service.name);
|
||||
END
|
||||
|
||||
ogs_sbi_message_free(&sbi_message);
|
||||
ogs_sbi_response_free(sbi_response);
|
||||
break;
|
||||
|
||||
case AMF_EVT_SBI_TIMER:
|
||||
ogs_assert(e);
|
||||
|
||||
switch(e->timer_id) {
|
||||
case AMF_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL:
|
||||
case AMF_TIMER_NF_INSTANCE_HEARTBEAT_INTERVAL:
|
||||
case AMF_TIMER_NF_INSTANCE_HEARTBEAT:
|
||||
case AMF_TIMER_NF_INSTANCE_VALIDITY:
|
||||
nf_instance = e->sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
ogs_assert(OGS_FSM_STATE(&nf_instance->sm));
|
||||
|
||||
ogs_fsm_dispatch(&nf_instance->sm, e);
|
||||
if (OGS_FSM_CHECK(&nf_instance->sm, amf_nf_state_de_registered)) {
|
||||
amf_nf_fsm_fini(nf_instance);
|
||||
ogs_sbi_nf_instance_remove(nf_instance);
|
||||
|
||||
} else if (OGS_FSM_CHECK(&nf_instance->sm,
|
||||
amf_nf_state_exception)) {
|
||||
ogs_error("State machine exception");
|
||||
}
|
||||
break;
|
||||
|
||||
case AMF_TIMER_SUBSCRIPTION_VALIDITY:
|
||||
subscription = e->sbi.data;
|
||||
ogs_assert(subscription);
|
||||
|
||||
ogs_info("Subscription validity expired [%s]", subscription->id);
|
||||
ogs_sbi_subscription_remove(subscription);
|
||||
|
||||
amf_sbi_send_nf_status_subscribe(subscription->client,
|
||||
amf_self()->nf_type, subscription->nf_instance_id);
|
||||
break;
|
||||
|
||||
default:
|
||||
ogs_error("Unknown timer[%s:%d]",
|
||||
amf_timer_get_name(e->timer_id), e->timer_id);
|
||||
}
|
||||
break;
|
||||
|
||||
case AMF_EVT_NGAP_LO_ACCEPT:
|
||||
sock = e->ngap.sock;
|
||||
ogs_assert(sock);
|
||||
addr = e->ngap.addr;
|
||||
ogs_assert(addr);
|
||||
|
||||
ogs_info("gNB-N1 accepted[%s] in master_sm module",
|
||||
OGS_ADDR(addr, buf));
|
||||
|
||||
gnb = amf_gnb_find_by_addr(addr);
|
||||
if (!gnb) {
|
||||
gnb = amf_gnb_add(sock, addr);
|
||||
ogs_assert(gnb);
|
||||
} else {
|
||||
ogs_warn("gNB context duplicated with IP-address [%s]!!!",
|
||||
OGS_ADDR(addr, buf));
|
||||
ogs_sock_destroy(sock);
|
||||
ogs_warn("N1 Socket Closed");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AMF_EVT_NGAP_LO_SCTP_COMM_UP:
|
||||
sock = e->ngap.sock;
|
||||
ogs_assert(sock);
|
||||
addr = e->ngap.addr;
|
||||
ogs_assert(addr);
|
||||
|
||||
max_num_of_ostreams = e->ngap.max_num_of_ostreams;
|
||||
|
||||
gnb = amf_gnb_find_by_addr(addr);
|
||||
if (!gnb) {
|
||||
gnb = amf_gnb_add(sock, addr);
|
||||
ogs_assert(gnb);
|
||||
} else {
|
||||
ogs_free(addr);
|
||||
}
|
||||
|
||||
gnb->max_num_of_ostreams =
|
||||
ogs_min(max_num_of_ostreams, gnb->max_num_of_ostreams);
|
||||
|
||||
ogs_debug("gNB-N1 SCTP_COMM_UP[%s] Max Num of Outbound Streams[%d]",
|
||||
OGS_ADDR(addr, buf), gnb->max_num_of_ostreams);
|
||||
|
||||
break;
|
||||
|
||||
case AMF_EVT_NGAP_LO_CONNREFUSED:
|
||||
sock = e->ngap.sock;
|
||||
ogs_assert(sock);
|
||||
addr = e->ngap.addr;
|
||||
ogs_assert(addr);
|
||||
|
||||
gnb = amf_gnb_find_by_addr(addr);
|
||||
ogs_free(addr);
|
||||
|
||||
if (gnb) {
|
||||
ogs_info("gNB-N1[%s] connection refused!!!",
|
||||
OGS_ADDR(addr, buf));
|
||||
amf_gnb_remove(gnb);
|
||||
} else {
|
||||
ogs_warn("gNB-N1[%s] connection refused, Already Removed!",
|
||||
OGS_ADDR(addr, buf));
|
||||
}
|
||||
|
||||
break;
|
||||
case AMF_EVT_NGAP_MESSAGE:
|
||||
sock = e->ngap.sock;
|
||||
ogs_assert(sock);
|
||||
addr = e->ngap.addr;
|
||||
ogs_assert(addr);
|
||||
pkbuf = e->pkbuf;
|
||||
ogs_assert(pkbuf);
|
||||
|
||||
gnb = amf_gnb_find_by_addr(addr);
|
||||
ogs_free(addr);
|
||||
|
||||
ogs_assert(gnb);
|
||||
ogs_assert(OGS_FSM_STATE(&gnb->sm));
|
||||
|
||||
rc = ogs_ngap_decode(&ngap_message, pkbuf);
|
||||
if (rc == OGS_OK) {
|
||||
e->gnb = gnb;
|
||||
e->ngap.message = &ngap_message;
|
||||
ogs_fsm_dispatch(&gnb->sm, e);
|
||||
} else {
|
||||
ogs_error("Cannot decode NGAP message");
|
||||
#if 0
|
||||
ngap_send_error_indication(
|
||||
gnb, NULL, NULL, NGAP_Cause_PR_protocol,
|
||||
NGAP_CauseProtocol_abstract_syntax_error_falsely_constructed_message);
|
||||
#endif
|
||||
}
|
||||
|
||||
ogs_ngap_free(&ngap_message);
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
break;
|
||||
|
||||
case AMF_EVT_NGAP_TIMER:
|
||||
#if 0
|
||||
gnb_ue = e->gnb_ue;
|
||||
ogs_assert(gnb_ue);
|
||||
gnb = e->gnb;
|
||||
ogs_assert(gnb);
|
||||
ogs_assert(OGS_FSM_STATE(&gnb->sm));
|
||||
|
||||
ogs_fsm_dispatch(&gnb->sm, e);
|
||||
#else
|
||||
ogs_fatal("Not implemeted");
|
||||
#endif
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
ogs_error("No handler for event %s", amf_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef AMF_SM_H
|
||||
#define AMF_SM_H
|
||||
|
||||
#include "event.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void amf_state_initial(ogs_fsm_t *s, amf_event_t *e);
|
||||
void amf_state_final(ogs_fsm_t *s, amf_event_t *e);
|
||||
void amf_state_operational(ogs_fsm_t *s, amf_event_t *e);
|
||||
|
||||
void amf_nf_fsm_init(ogs_sbi_nf_instance_t *nf_instance);
|
||||
void amf_nf_fsm_fini(ogs_sbi_nf_instance_t *nf_instance);
|
||||
|
||||
void amf_nf_state_initial(ogs_fsm_t *s, amf_event_t *e);
|
||||
void amf_nf_state_final(ogs_fsm_t *s, amf_event_t *e);
|
||||
void amf_nf_state_will_register(ogs_fsm_t *s, amf_event_t *e);
|
||||
void amf_nf_state_registered(ogs_fsm_t *s, amf_event_t *e);
|
||||
void amf_nf_state_de_registered(ogs_fsm_t *s, amf_event_t *e);
|
||||
void amf_nf_state_exception(ogs_fsm_t *s, amf_event_t *e);
|
||||
|
||||
void ngap_state_initial(ogs_fsm_t *s, amf_event_t *e);
|
||||
void ngap_state_final(ogs_fsm_t *s, amf_event_t *e);
|
||||
void ngap_state_operational(ogs_fsm_t *s, amf_event_t *e);
|
||||
void ngap_state_exception(ogs_fsm_t *s, amf_event_t *e);
|
||||
|
||||
#define amf_sm_debug(__pe) \
|
||||
ogs_debug("%s(): %s", __func__, amf_event_get_name(__pe))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AMF_SM_H */
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ogs-app.h"
|
||||
|
||||
int app_initialize(const char *const argv[])
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = amf_initialize();
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("Failed to intialize AMF");
|
||||
return rv;
|
||||
}
|
||||
ogs_info("AMF initialize...done");
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
void app_terminate(void)
|
||||
{
|
||||
amf_terminate();
|
||||
ogs_info("AMF terminate...done");
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef AMF_CONTEXT_H
|
||||
#define AMF_CONTEXT_H
|
||||
|
||||
#include "ogs-app.h"
|
||||
#include "ogs-sbi.h"
|
||||
#include "ogs-sctp.h"
|
||||
#include "ogs-ngap.h"
|
||||
#include "ogs-nas-5gs.h"
|
||||
|
||||
#include "amf-sm.h"
|
||||
#include "timer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_NUM_OF_SERVED_GUAMI 8
|
||||
|
||||
extern int __amf_log_domain;
|
||||
|
||||
#undef OGS_LOG_DOMAIN
|
||||
#define OGS_LOG_DOMAIN __amf_log_domain
|
||||
|
||||
typedef uint32_t amf_m_tmsi_t;
|
||||
|
||||
typedef struct amf_context_s {
|
||||
ogs_queue_t *queue; /* Queue for processing UPF control */
|
||||
ogs_timer_mgr_t *timer_mgr; /* Timer Manager */
|
||||
ogs_pollset_t *pollset; /* Poll Set for I/O Multiplexing */
|
||||
|
||||
OpenAPI_nf_type_e nf_type;
|
||||
const char *amf_name;
|
||||
|
||||
/* Served GUMME */
|
||||
uint8_t num_of_served_guami;
|
||||
struct {
|
||||
ogs_plmn_id_t plmn_id;
|
||||
ogs_amf_id_t amf_id;
|
||||
} served_guami[MAX_NUM_OF_SERVED_GUAMI];
|
||||
|
||||
/* Served TAI */
|
||||
uint8_t num_of_served_tai;
|
||||
struct {
|
||||
ogs_5gs_tai0_list_t list0;
|
||||
ogs_5gs_tai2_list_t list2;
|
||||
} served_tai[OGS_MAX_NUM_OF_SERVED_TAI];
|
||||
|
||||
/* PLMN Support */
|
||||
uint8_t num_of_plmn_support;
|
||||
struct {
|
||||
ogs_plmn_id_t plmn_id;
|
||||
int num_of_s_nssai;
|
||||
ogs_s_nssai_t s_nssai[OGS_MAX_NUM_OF_S_NSSAI];
|
||||
} plmn_support[OGS_MAX_NUM_OF_PLMN];
|
||||
|
||||
/* defined in 'nas_ies.h'
|
||||
* #define NAS_SECURITY_ALGORITHMS_EIA0 0
|
||||
* #define NAS_SECURITY_ALGORITHMS_128_EEA1 1
|
||||
* #define NAS_SECURITY_ALGORITHMS_128_EEA2 2
|
||||
* #define NAS_SECURITY_ALGORITHMS_128_EEA3 3 */
|
||||
uint8_t num_of_ciphering_order;
|
||||
uint8_t ciphering_order[OGS_MAX_NUM_OF_ALGORITHM];
|
||||
/* defined in 'nas_ies.h'
|
||||
* #define NAS_SECURITY_ALGORITHMS_EIA0 0
|
||||
* #define NAS_SECURITY_ALGORITHMS_128_EIA1 1
|
||||
* #define NAS_SECURITY_ALGORITHMS_128_EIA1 2
|
||||
* #define NAS_SECURITY_ALGORITHMS_128_EIA3 3 */
|
||||
uint8_t num_of_integrity_order;
|
||||
uint8_t integrity_order[OGS_MAX_NUM_OF_ALGORITHM];
|
||||
|
||||
/* Network Name */
|
||||
ogs_nas_network_name_t short_name; /* Network short name */
|
||||
ogs_nas_network_name_t full_name; /* Network Full Name */
|
||||
|
||||
/* M-TMSI Pool */
|
||||
OGS_POOL(m_tmsi, amf_m_tmsi_t);
|
||||
|
||||
/* NGSetupResponse */
|
||||
uint8_t relative_capacity;
|
||||
|
||||
uint16_t ngap_port; /* Default NGAP Port */
|
||||
|
||||
ogs_list_t ngap_list; /* AMF NGAP IPv4 Server List */
|
||||
ogs_list_t ngap_list6; /* AMF NGAP IPv6 Server List */
|
||||
|
||||
ogs_list_t gnb_list; /* ENB S1AP Client List */
|
||||
ogs_hash_t *gnb_addr_hash; /* hash table for GNB Address */
|
||||
ogs_hash_t *gnb_id_hash; /* hash table for GNB-ID */
|
||||
} amf_context_t;
|
||||
|
||||
typedef struct amf_gnb_s {
|
||||
ogs_lnode_t lnode;
|
||||
|
||||
ogs_fsm_t sm; /* A state machine */
|
||||
|
||||
uint32_t gnb_id; /* eNB_ID received from eNB */
|
||||
int sock_type; /* SOCK_STREAM or SOCK_SEQPACKET */
|
||||
ogs_sock_t *sock; /* eNB S1AP Socket */
|
||||
ogs_sockaddr_t *addr; /* eNB S1AP Address */
|
||||
ogs_poll_t *poll; /* eNB S1AP Poll */
|
||||
|
||||
struct {
|
||||
bool ng_setup_success; /* eNB S1AP Setup complete successfuly */
|
||||
} state;
|
||||
|
||||
uint16_t max_num_of_ostreams;/* SCTP Max num of outbound streams */
|
||||
uint16_t ostream_id; /* gnb_ostream_id generator */
|
||||
|
||||
|
||||
uint8_t num_of_supported_ta_list;
|
||||
ogs_5gs_tai_t supported_ta_list[OGS_MAX_NUM_OF_TAI*OGS_MAX_NUM_OF_BPLMN];
|
||||
|
||||
ogs_list_t gnb_ue_list;
|
||||
|
||||
} amf_gnb_t;
|
||||
|
||||
void amf_context_init(void);
|
||||
void amf_context_final(void);
|
||||
amf_context_t *amf_self(void);
|
||||
|
||||
int amf_context_parse_config(void);
|
||||
|
||||
amf_gnb_t *amf_gnb_add(ogs_sock_t *sock, ogs_sockaddr_t *addr);
|
||||
int amf_gnb_remove(amf_gnb_t *gnb);
|
||||
int amf_gnb_remove_all(void);
|
||||
amf_gnb_t *amf_gnb_find_by_addr(ogs_sockaddr_t *addr);
|
||||
amf_gnb_t *amf_gnb_find_by_gnb_id(uint32_t gnb_id);
|
||||
int amf_gnb_set_gnb_id(amf_gnb_t *gnb, uint32_t gnb_id);
|
||||
int amf_gnb_sock_type(ogs_sock_t *sock);
|
||||
|
||||
int amf_find_served_tai(ogs_5gs_tai_t *tai);
|
||||
|
||||
int amf_m_tmsi_pool_generate(void);
|
||||
amf_m_tmsi_t *amf_m_tmsi_alloc(void);
|
||||
int amf_m_tmsi_free(amf_m_tmsi_t *tmsi);
|
||||
|
||||
#if 0
|
||||
uint8_t amf_selected_int_algorithm(amf_ue_t *amf_ue);
|
||||
uint8_t amf_selected_enc_algorithm(amf_ue_t *amf_ue);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AMF_CONTEXT_H */
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "event.h"
|
||||
#include "context.h"
|
||||
|
||||
#define EVENT_POOL 32 /* FIXME : 32 */
|
||||
static OGS_POOL(pool, amf_event_t);
|
||||
|
||||
void amf_event_init(void)
|
||||
{
|
||||
ogs_pool_init(&pool, EVENT_POOL);
|
||||
|
||||
amf_self()->queue = ogs_queue_create(EVENT_POOL);
|
||||
ogs_assert(amf_self()->queue);
|
||||
amf_self()->timer_mgr = ogs_timer_mgr_create();
|
||||
ogs_assert(amf_self()->timer_mgr);
|
||||
amf_self()->pollset = ogs_pollset_create();
|
||||
ogs_assert(amf_self()->pollset);
|
||||
}
|
||||
|
||||
void amf_event_final(void)
|
||||
{
|
||||
if (amf_self()->pollset)
|
||||
ogs_pollset_destroy(amf_self()->pollset);
|
||||
if (amf_self()->timer_mgr)
|
||||
ogs_timer_mgr_destroy(amf_self()->timer_mgr);
|
||||
if (amf_self()->queue)
|
||||
ogs_queue_destroy(amf_self()->queue);
|
||||
|
||||
ogs_pool_final(&pool);
|
||||
}
|
||||
|
||||
amf_event_t *amf_event_new(amf_event_e id)
|
||||
{
|
||||
amf_event_t *e = NULL;
|
||||
|
||||
ogs_pool_alloc(&pool, &e);
|
||||
ogs_assert(e);
|
||||
memset(e, 0, sizeof(*e));
|
||||
|
||||
e->id = id;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void amf_event_free(amf_event_t *e)
|
||||
{
|
||||
ogs_assert(e);
|
||||
ogs_pool_free(&pool, e);
|
||||
}
|
||||
|
||||
const char *amf_event_get_name(amf_event_t *e)
|
||||
{
|
||||
if (e == NULL)
|
||||
return OGS_FSM_NAME_INIT_SIG;
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
return OGS_FSM_NAME_ENTRY_SIG;
|
||||
case OGS_FSM_EXIT_SIG:
|
||||
return OGS_FSM_NAME_EXIT_SIG;
|
||||
|
||||
case AMF_EVT_SBI_SERVER:
|
||||
return "AMF_EVT_SBI_SERVER";
|
||||
case AMF_EVT_SBI_CLIENT:
|
||||
return "AMF_EVT_SBI_CLIENT";
|
||||
case AMF_EVT_SBI_TIMER:
|
||||
return "AMF_EVT_SBI_TIMER";
|
||||
|
||||
case AMF_EVT_NGAP_MESSAGE:
|
||||
return "AMF_EVT_NGAP_MESSAGE";
|
||||
case AMF_EVT_NGAP_TIMER:
|
||||
return "AMF_EVT_NGAP_TIMER";
|
||||
case AMF_EVT_NGAP_LO_ACCEPT:
|
||||
return "AMF_EVT_NGAP_LO_ACCEPT";
|
||||
case AMF_EVT_NGAP_LO_SCTP_COMM_UP:
|
||||
return "AMF_EVT_NGAP_LO_SCTP_COMM_UP";
|
||||
case AMF_EVT_NGAP_LO_CONNREFUSED:
|
||||
return "AMF_EVT_NGAP_LO_CONNREFUSED";
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "UNKNOWN_EVENT";
|
||||
}
|
||||
|
||||
void amf_sctp_event_push(amf_event_e id,
|
||||
void *sock, ogs_sockaddr_t *addr, ogs_pkbuf_t *pkbuf,
|
||||
uint16_t max_num_of_istreams, uint16_t max_num_of_ostreams)
|
||||
{
|
||||
amf_event_t *e = NULL;
|
||||
int rv;
|
||||
|
||||
ogs_assert(id);
|
||||
ogs_assert(sock);
|
||||
ogs_assert(addr);
|
||||
|
||||
e = amf_event_new(id);
|
||||
ogs_assert(e);
|
||||
|
||||
e->pkbuf = pkbuf;
|
||||
|
||||
e->ngap.sock = sock;
|
||||
e->ngap.addr = addr;
|
||||
e->ngap.max_num_of_istreams = max_num_of_istreams;
|
||||
e->ngap.max_num_of_ostreams = max_num_of_ostreams;
|
||||
|
||||
rv = ogs_queue_push(amf_self()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
|
||||
ogs_free(e->ngap.addr);
|
||||
if (e->pkbuf)
|
||||
ogs_pkbuf_free(e->pkbuf);
|
||||
amf_event_free(e);
|
||||
}
|
||||
#if HAVE_USRSCTP
|
||||
else {
|
||||
ogs_pollset_notify(amf_self()->pollset);
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef AMF_EVENT_H
|
||||
#define AMF_EVENT_H
|
||||
|
||||
#include "ogs-core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct ogs_sbi_server_s ogs_sbi_server_t;
|
||||
typedef struct ogs_sbi_session_s ogs_sbi_session_t;
|
||||
typedef struct ogs_sbi_request_s ogs_sbi_request_t;
|
||||
typedef struct ogs_sbi_response_s ogs_sbi_response_t;
|
||||
typedef struct ogs_sbi_message_s ogs_sbi_message_t;
|
||||
typedef struct ogs_sbi_nf_instance_s ogs_sbi_nf_instance_t;
|
||||
typedef struct ogs_sbi_subscription_s ogs_sbi_subscription_t;
|
||||
|
||||
typedef enum {
|
||||
AMF_EVT_BASE = OGS_FSM_USER_SIG,
|
||||
|
||||
AMF_EVT_SBI_SERVER,
|
||||
AMF_EVT_SBI_CLIENT,
|
||||
AMF_EVT_SBI_TIMER,
|
||||
|
||||
AMF_EVT_NGAP_MESSAGE,
|
||||
AMF_EVT_NGAP_TIMER,
|
||||
AMF_EVT_NGAP_LO_ACCEPT,
|
||||
AMF_EVT_NGAP_LO_SCTP_COMM_UP,
|
||||
AMF_EVT_NGAP_LO_CONNREFUSED,
|
||||
|
||||
AMF_EVT_TOP,
|
||||
|
||||
} amf_event_e;
|
||||
|
||||
typedef struct amf_gnb_s amf_gnb_t;
|
||||
typedef struct ogs_nas_5gs_message_s ogs_nas_5gs_message_t;
|
||||
typedef struct NGAP_NGAP_PDU ogs_ngap_message_t;
|
||||
typedef long NGAP_ProcedureCode_t;
|
||||
|
||||
typedef struct amf_event_s {
|
||||
int id;
|
||||
ogs_pkbuf_t *pkbuf;
|
||||
int timer_id;
|
||||
|
||||
struct {
|
||||
ogs_sock_t *sock;
|
||||
ogs_sockaddr_t *addr;
|
||||
uint16_t max_num_of_istreams;
|
||||
uint16_t max_num_of_ostreams;
|
||||
|
||||
NGAP_ProcedureCode_t code;
|
||||
ogs_ngap_message_t *message;
|
||||
} ngap;
|
||||
|
||||
struct {
|
||||
/* OGS_EVT_SBI_SERVER */
|
||||
ogs_sbi_request_t *request;
|
||||
ogs_sbi_session_t *session;
|
||||
ogs_sbi_server_t *server;
|
||||
|
||||
/* OGS_EVT_SBI_CLIENT */
|
||||
ogs_sbi_response_t *response;
|
||||
void *data;
|
||||
|
||||
ogs_sbi_message_t *message;
|
||||
} sbi;
|
||||
|
||||
amf_gnb_t *gnb;
|
||||
} amf_event_t;
|
||||
|
||||
void amf_event_init(void);
|
||||
void amf_event_final(void);
|
||||
|
||||
amf_event_t *amf_event_new(amf_event_e id);
|
||||
void amf_event_free(amf_event_t *e);
|
||||
|
||||
const char *amf_event_get_name(amf_event_t *e);
|
||||
|
||||
void amf_sctp_event_push(amf_event_e id,
|
||||
void *sock, ogs_sockaddr_t *addr, ogs_pkbuf_t *pkbuf,
|
||||
uint16_t max_num_of_istreams, uint16_t max_num_of_ostreams);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AMF_EVENT_H */
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "context.h"
|
||||
|
||||
static ogs_thread_t *thread;
|
||||
static void amf_main(void *data);
|
||||
static int initialized = 0;
|
||||
|
||||
int amf_initialize()
|
||||
{
|
||||
int rv;
|
||||
|
||||
amf_context_init();
|
||||
amf_event_init(); /* Create event with poll, timer */
|
||||
ogs_sbi_context_init(amf_self()->pollset, amf_self()->timer_mgr);
|
||||
|
||||
rv = ogs_sbi_context_parse_config("amf", "nrf");
|
||||
if (rv != OGS_OK) return rv;
|
||||
|
||||
rv = amf_context_parse_config();
|
||||
if (rv != OGS_OK) return rv;
|
||||
|
||||
rv = ogs_log_config_domain(
|
||||
ogs_config()->logger.domain, ogs_config()->logger.level);
|
||||
if (rv != OGS_OK) return rv;
|
||||
|
||||
thread = ogs_thread_create(amf_main, NULL);
|
||||
if (!thread) return OGS_ERROR;
|
||||
|
||||
initialized = 1;
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
static ogs_timer_t *t_termination_holding = NULL;
|
||||
|
||||
static void event_termination(void)
|
||||
{
|
||||
ogs_sbi_nf_instance_t *nf_instance = NULL;
|
||||
|
||||
/* Sending NF Instance De-registeration to NRF */
|
||||
ogs_list_for_each(&ogs_sbi_self()->nf_instance_list, nf_instance)
|
||||
amf_nf_fsm_fini(nf_instance);
|
||||
|
||||
/* Starting holding timer */
|
||||
t_termination_holding = ogs_timer_add(amf_self()->timer_mgr, NULL, NULL);
|
||||
ogs_assert(t_termination_holding);
|
||||
#define TERMINATION_HOLDING_TIME ogs_time_from_msec(300)
|
||||
ogs_timer_start(t_termination_holding, TERMINATION_HOLDING_TIME);
|
||||
|
||||
/* Sending termination event to the queue */
|
||||
ogs_queue_term(amf_self()->queue);
|
||||
ogs_pollset_notify(amf_self()->pollset);
|
||||
}
|
||||
|
||||
void amf_terminate(void)
|
||||
{
|
||||
if (!initialized) return;
|
||||
|
||||
/* Daemon terminating */
|
||||
event_termination();
|
||||
ogs_thread_destroy(thread);
|
||||
ogs_timer_delete(t_termination_holding);
|
||||
|
||||
amf_context_final();
|
||||
ogs_sbi_context_final();
|
||||
|
||||
amf_event_final(); /* Destroy event */
|
||||
}
|
||||
|
||||
static void amf_main(void *data)
|
||||
{
|
||||
ogs_fsm_t amf_sm;
|
||||
int rv;
|
||||
|
||||
ogs_fsm_create(&amf_sm, amf_state_initial, amf_state_final);
|
||||
ogs_fsm_init(&amf_sm, 0);
|
||||
|
||||
for ( ;; ) {
|
||||
ogs_pollset_poll(amf_self()->pollset,
|
||||
ogs_timer_mgr_next(amf_self()->timer_mgr));
|
||||
|
||||
/*
|
||||
* After ogs_pollset_poll(), ogs_timer_mgr_expire() must be called.
|
||||
*
|
||||
* The reason is why ogs_timer_mgr_next() can get the corrent value
|
||||
* when ogs_timer_stop() is called internally in ogs_timer_mgr_expire().
|
||||
*
|
||||
* You should not use event-queue before ogs_timer_mgr_expire().
|
||||
* In this case, ogs_timer_mgr_expire() does not work
|
||||
* because 'if rv == OGS_DONE' statement is exiting and
|
||||
* not calling ogs_timer_mgr_expire().
|
||||
*/
|
||||
ogs_timer_mgr_expire(amf_self()->timer_mgr);
|
||||
|
||||
for ( ;; ) {
|
||||
amf_event_t *e = NULL;
|
||||
|
||||
rv = ogs_queue_trypop(amf_self()->queue, (void**)&e);
|
||||
ogs_assert(rv != OGS_ERROR);
|
||||
|
||||
if (rv == OGS_DONE)
|
||||
goto done;
|
||||
|
||||
if (rv == OGS_RETRY)
|
||||
break;
|
||||
|
||||
ogs_assert(e);
|
||||
ogs_fsm_dispatch(&amf_sm, e);
|
||||
amf_event_free(e);
|
||||
}
|
||||
}
|
||||
done:
|
||||
|
||||
ogs_fsm_fini(&amf_sm, 0);
|
||||
ogs_fsm_delete(&amf_sm);
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
# Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
|
||||
# This file is part of Open5GS.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
libamf_sources = files('''
|
||||
context.c
|
||||
event.c
|
||||
timer.c
|
||||
|
||||
nnrf-handler.c
|
||||
nnrf-build.c
|
||||
sbi-path.c
|
||||
nf-sm.c
|
||||
|
||||
ngap-sctp.c
|
||||
ngap-build.c
|
||||
ngap-handler.c
|
||||
ngap-path.c
|
||||
ngap-sm.c
|
||||
|
||||
amf-sm.c
|
||||
|
||||
init.c
|
||||
'''.split())
|
||||
|
||||
libamf = static_library('amf',
|
||||
sources : libamf_sources,
|
||||
link_with : libipfw,
|
||||
dependencies : [libapp_dep,
|
||||
libsctp_dep,
|
||||
libngap_dep,
|
||||
libnas_5gs_dep,
|
||||
libsbi_dep],
|
||||
install : false)
|
||||
|
||||
libamf_dep = declare_dependency(
|
||||
link_with : libamf,
|
||||
dependencies : [libapp_dep,
|
||||
libsctp_dep,
|
||||
libngap_dep,
|
||||
libnas_5gs_dep,
|
||||
libsbi_dep])
|
||||
|
||||
amf_sources = files('''
|
||||
app.c
|
||||
../main.c
|
||||
'''.split())
|
||||
|
||||
executable('open5gs-amfd',
|
||||
sources : amf_sources,
|
||||
c_args : '-DDEFAULT_CONFIG_FILENAME="@0@/amf.yaml"'.format(open5gs_sysconfdir),
|
||||
include_directories : srcinc,
|
||||
dependencies : libamf_dep,
|
||||
install_rpath : libdir,
|
||||
install : true)
|
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "context.h"
|
||||
|
||||
#include "sbi-path.h"
|
||||
#include "nnrf-handler.h"
|
||||
|
||||
void amf_nf_fsm_init(ogs_sbi_nf_instance_t *nf_instance)
|
||||
{
|
||||
amf_event_t e;
|
||||
|
||||
ogs_assert(nf_instance);
|
||||
|
||||
e.sbi.data = nf_instance;
|
||||
|
||||
ogs_fsm_create(&nf_instance->sm,
|
||||
amf_nf_state_initial, amf_nf_state_final);
|
||||
ogs_fsm_init(&nf_instance->sm, &e);
|
||||
}
|
||||
|
||||
void amf_nf_fsm_fini(ogs_sbi_nf_instance_t *nf_instance)
|
||||
{
|
||||
amf_event_t e;
|
||||
|
||||
ogs_assert(nf_instance);
|
||||
e.sbi.data = nf_instance;
|
||||
|
||||
ogs_fsm_fini(&nf_instance->sm, &e);
|
||||
ogs_fsm_delete(&nf_instance->sm);
|
||||
}
|
||||
|
||||
void amf_nf_state_initial(ogs_fsm_t *s, amf_event_t *e)
|
||||
{
|
||||
ogs_sbi_nf_instance_t *nf_instance = NULL;
|
||||
|
||||
ogs_assert(s);
|
||||
ogs_assert(e);
|
||||
|
||||
amf_sm_debug(e);
|
||||
|
||||
nf_instance = e->sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
ogs_assert(nf_instance->id);
|
||||
|
||||
nf_instance->t_registration_interval = ogs_timer_add(amf_self()->timer_mgr,
|
||||
amf_timer_nf_instance_registration_interval, nf_instance);
|
||||
ogs_assert(nf_instance->t_registration_interval);
|
||||
nf_instance->t_heartbeat_interval = ogs_timer_add(amf_self()->timer_mgr,
|
||||
amf_timer_nf_instance_heartbeat_interval, nf_instance);
|
||||
ogs_assert(nf_instance->t_heartbeat_interval);
|
||||
nf_instance->t_heartbeat = ogs_timer_add(amf_self()->timer_mgr,
|
||||
amf_timer_nf_instance_heartbeat, nf_instance);
|
||||
ogs_assert(nf_instance->t_heartbeat);
|
||||
nf_instance->t_validity = ogs_timer_add(amf_self()->timer_mgr,
|
||||
amf_timer_nf_instance_validity, nf_instance);
|
||||
ogs_assert(nf_instance->t_validity);
|
||||
|
||||
if (NF_INSTANCE_IS_SELF(nf_instance->id)) {
|
||||
OGS_FSM_TRAN(s, &amf_nf_state_will_register);
|
||||
} else {
|
||||
OGS_FSM_TRAN(s, &amf_nf_state_registered);
|
||||
}
|
||||
}
|
||||
|
||||
void amf_nf_state_final(ogs_fsm_t *s, amf_event_t *e)
|
||||
{
|
||||
ogs_sbi_nf_instance_t *nf_instance = NULL;
|
||||
|
||||
ogs_assert(s);
|
||||
ogs_assert(e);
|
||||
|
||||
amf_sm_debug(e);
|
||||
|
||||
nf_instance = e->sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
|
||||
ogs_timer_delete(nf_instance->t_registration_interval);
|
||||
ogs_timer_delete(nf_instance->t_heartbeat_interval);
|
||||
ogs_timer_delete(nf_instance->t_heartbeat);
|
||||
ogs_timer_delete(nf_instance->t_validity);
|
||||
}
|
||||
|
||||
void amf_nf_state_will_register(ogs_fsm_t *s, amf_event_t *e)
|
||||
{
|
||||
ogs_sbi_nf_instance_t *nf_instance = NULL;
|
||||
ogs_sbi_client_t *client = NULL;
|
||||
ogs_sbi_message_t *message = NULL;
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
|
||||
ogs_assert(s);
|
||||
ogs_assert(e);
|
||||
|
||||
amf_sm_debug(e);
|
||||
|
||||
nf_instance = e->sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
ogs_timer_start(nf_instance->t_registration_interval,
|
||||
amf_timer_cfg(AMF_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL)->
|
||||
duration);
|
||||
|
||||
amf_sbi_send_nf_register(nf_instance);
|
||||
break;
|
||||
|
||||
case OGS_FSM_EXIT_SIG:
|
||||
ogs_timer_stop(nf_instance->t_registration_interval);
|
||||
break;
|
||||
|
||||
case AMF_EVT_SBI_CLIENT:
|
||||
message = e->sbi.message;
|
||||
ogs_assert(message);
|
||||
|
||||
SWITCH(message->h.service.name)
|
||||
CASE(OGS_SBI_SERVICE_NAME_NRF_NFM)
|
||||
|
||||
SWITCH(message->h.resource.name)
|
||||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||
|
||||
if (message->res_status == OGS_SBI_HTTP_STATUS_OK ||
|
||||
message->res_status == OGS_SBI_HTTP_STATUS_CREATED) {
|
||||
amf_nnrf_handle_nf_register(nf_instance, message);
|
||||
OGS_FSM_TRAN(s, &amf_nf_state_registered);
|
||||
} else {
|
||||
ogs_error("HTTP Response Status Code [%d]",
|
||||
message->res_status);
|
||||
OGS_FSM_TRAN(s, &amf_nf_state_exception);
|
||||
}
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
ogs_error("Invalid resource name [%s]",
|
||||
message->h.resource.name);
|
||||
END
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
ogs_error("Invalid API name [%s]", message->h.service.name);
|
||||
END
|
||||
break;
|
||||
|
||||
case AMF_EVT_SBI_TIMER:
|
||||
switch(e->timer_id) {
|
||||
case AMF_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL:
|
||||
client = nf_instance->client;
|
||||
ogs_assert(client);
|
||||
addr = client->addr;
|
||||
ogs_assert(addr);
|
||||
|
||||
ogs_warn("Retry to registration with NRF [%s]", nf_instance->id);
|
||||
|
||||
ogs_timer_start(nf_instance->t_registration_interval,
|
||||
amf_timer_cfg(AMF_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL)->
|
||||
duration);
|
||||
|
||||
amf_sbi_send_nf_register(nf_instance);
|
||||
break;
|
||||
|
||||
default:
|
||||
ogs_error("Unknown timer[%s:%d]",
|
||||
amf_timer_get_name(e->timer_id), e->timer_id);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ogs_error("Unknown event %s", amf_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void amf_nf_state_registered(ogs_fsm_t *s, amf_event_t *e)
|
||||
{
|
||||
ogs_sbi_nf_instance_t *nf_instance = NULL;
|
||||
ogs_sbi_client_t *client = NULL;
|
||||
ogs_sbi_message_t *message = NULL;
|
||||
ogs_assert(s);
|
||||
ogs_assert(e);
|
||||
|
||||
amf_sm_debug(e);
|
||||
|
||||
nf_instance = e->sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
if (NF_INSTANCE_IS_SELF(nf_instance->id)) {
|
||||
ogs_info("NF registered [%s]", nf_instance->id);
|
||||
|
||||
client = nf_instance->client;
|
||||
ogs_assert(client);
|
||||
|
||||
if (nf_instance->time.heartbeat) {
|
||||
ogs_timer_start(nf_instance->t_heartbeat_interval,
|
||||
ogs_time_from_sec(nf_instance->time.heartbeat));
|
||||
ogs_timer_start(nf_instance->t_heartbeat,
|
||||
ogs_time_from_sec(nf_instance->time.heartbeat *
|
||||
OGS_SBI_HEARTBEAT_RETRYCOUNT));
|
||||
}
|
||||
|
||||
amf_sbi_send_nf_status_subscribe(client,
|
||||
amf_self()->nf_type, nf_instance->id);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case OGS_FSM_EXIT_SIG:
|
||||
if (NF_INSTANCE_IS_SELF(nf_instance->id)) {
|
||||
ogs_info("NF de-registered [%s]", nf_instance->id);
|
||||
|
||||
if (nf_instance->time.heartbeat) {
|
||||
ogs_timer_stop(nf_instance->t_heartbeat_interval);
|
||||
ogs_timer_stop(nf_instance->t_heartbeat);
|
||||
}
|
||||
|
||||
amf_sbi_send_nf_de_register(nf_instance);
|
||||
}
|
||||
break;
|
||||
|
||||
case AMF_EVT_SBI_CLIENT:
|
||||
message = e->sbi.message;
|
||||
ogs_assert(message);
|
||||
|
||||
SWITCH(message->h.service.name)
|
||||
CASE(OGS_SBI_SERVICE_NAME_NRF_NFM)
|
||||
|
||||
SWITCH(message->h.resource.name)
|
||||
CASE(OGS_SBI_RESOURCE_NAME_NF_INSTANCES)
|
||||
|
||||
if (message->res_status == OGS_SBI_HTTP_STATUS_NO_CONTENT ||
|
||||
message->res_status == OGS_SBI_HTTP_STATUS_OK) {
|
||||
if (nf_instance->time.heartbeat)
|
||||
ogs_timer_start(nf_instance->t_heartbeat,
|
||||
ogs_time_from_sec(nf_instance->time.heartbeat *
|
||||
OGS_SBI_HEARTBEAT_RETRYCOUNT));
|
||||
} else {
|
||||
ogs_error("HTTP response error : %d", message->res_status);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
ogs_error("Invalid resource name [%s]",
|
||||
message->h.resource.name);
|
||||
END
|
||||
break;
|
||||
|
||||
DEFAULT
|
||||
ogs_error("Invalid API name [%s]", message->h.service.name);
|
||||
END
|
||||
break;
|
||||
|
||||
case AMF_EVT_SBI_TIMER:
|
||||
switch(e->timer_id) {
|
||||
case AMF_TIMER_NF_INSTANCE_HEARTBEAT_INTERVAL:
|
||||
if (nf_instance->time.heartbeat) {
|
||||
ogs_timer_start(nf_instance->t_heartbeat_interval,
|
||||
ogs_time_from_sec(nf_instance->time.heartbeat));
|
||||
}
|
||||
|
||||
amf_sbi_send_nf_update(nf_instance);
|
||||
break;
|
||||
|
||||
case AMF_TIMER_NF_INSTANCE_HEARTBEAT:
|
||||
OGS_FSM_TRAN(s, &amf_nf_state_will_register);
|
||||
break;
|
||||
|
||||
case AMF_TIMER_NF_INSTANCE_VALIDITY:
|
||||
if (NF_INSTANCE_IS_OTHERS(nf_instance->id)) {
|
||||
ogs_info("NF expired [%s]", nf_instance->id);
|
||||
OGS_FSM_TRAN(s, &amf_nf_state_de_registered);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ogs_error("Unknown timer[%s:%d]",
|
||||
amf_timer_get_name(e->timer_id), e->timer_id);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ogs_error("Unknown event %s", amf_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void amf_nf_state_de_registered(ogs_fsm_t *s, amf_event_t *e)
|
||||
{
|
||||
ogs_sbi_nf_instance_t *nf_instance = NULL;
|
||||
ogs_assert(s);
|
||||
ogs_assert(e);
|
||||
|
||||
amf_sm_debug(e);
|
||||
|
||||
nf_instance = e->sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
if (NF_INSTANCE_IS_SELF(nf_instance->id)) {
|
||||
ogs_info("NF de-registered [%s]", nf_instance->id);
|
||||
}
|
||||
break;
|
||||
|
||||
case OGS_FSM_EXIT_SIG:
|
||||
break;
|
||||
|
||||
default:
|
||||
ogs_error("Unknown event %s", amf_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void amf_nf_state_exception(ogs_fsm_t *s, amf_event_t *e)
|
||||
{
|
||||
ogs_sbi_nf_instance_t *nf_instance = NULL;
|
||||
ogs_sbi_client_t *client = NULL;
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
ogs_assert(s);
|
||||
ogs_assert(e);
|
||||
|
||||
amf_sm_debug(e);
|
||||
|
||||
nf_instance = e->sbi.data;
|
||||
ogs_assert(nf_instance);
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
if (NF_INSTANCE_IS_SELF(nf_instance->id)) {
|
||||
ogs_timer_start(nf_instance->t_registration_interval,
|
||||
amf_timer_cfg(AMF_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL)->
|
||||
duration);
|
||||
}
|
||||
break;
|
||||
|
||||
case OGS_FSM_EXIT_SIG:
|
||||
if (NF_INSTANCE_IS_SELF(nf_instance->id)) {
|
||||
ogs_timer_stop(nf_instance->t_registration_interval);
|
||||
}
|
||||
break;
|
||||
|
||||
case AMF_EVT_SBI_TIMER:
|
||||
switch(e->timer_id) {
|
||||
case AMF_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL:
|
||||
client = nf_instance->client;
|
||||
ogs_assert(client);
|
||||
addr = client->addr;
|
||||
ogs_assert(addr);
|
||||
|
||||
ogs_warn("Retry to registration with NRF [%s]", nf_instance->id);
|
||||
|
||||
OGS_FSM_TRAN(s, &amf_nf_state_will_register);
|
||||
break;
|
||||
|
||||
default:
|
||||
ogs_error("Unknown timer[%s:%d]",
|
||||
amf_timer_get_name(e->timer_id), e->timer_id);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ogs_error("Unknown event %s", amf_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NGAP_BUILD_H
|
||||
#define NGAP_BUILD_H
|
||||
|
||||
#include "context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
ogs_pkbuf_t *ngap_build_setup_rsp(void);
|
||||
ogs_pkbuf_t *ngap_build_setup_failure(
|
||||
NGAP_Cause_PR group, long cause, long time_to_wait);
|
||||
|
||||
#if 0
|
||||
ogs_pkbuf_t *ngap_build_downlink_nas_transport(
|
||||
gnb_ue_t *gnb_ue, ogs_pkbuf_t *emmbuf);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_initial_context_setup_request(
|
||||
amf_ue_t *amf_ue, ogs_pkbuf_t *emmbuf);
|
||||
ogs_pkbuf_t *ngap_build_ue_context_modification_request(amf_ue_t *amf_ue);
|
||||
ogs_pkbuf_t *ngap_build_ue_context_release_command(
|
||||
gnb_ue_t *gnb_ue, NGAP_Cause_PR group, long cause);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_e_rab_setup_request(
|
||||
amf_bearer_t *bearer, ogs_pkbuf_t *esmbuf);
|
||||
ogs_pkbuf_t *ngap_build_e_rab_modify_request(
|
||||
amf_bearer_t *bearer, ogs_pkbuf_t *esmbuf);
|
||||
ogs_pkbuf_t *ngap_build_e_rab_release_command(
|
||||
amf_bearer_t *bearer, ogs_pkbuf_t *esmbuf, NGAP_Cause_PR group, long cause);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_paging(
|
||||
amf_ue_t *amf_ue, NGAP_CNDomain_t cn_domain);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_amf_configuration_transfer(
|
||||
NGAP_SONConfigurationTransfer_t *son_configuration_transfer);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_path_switch_ack(amf_ue_t *amf_ue);
|
||||
ogs_pkbuf_t *ngap_build_path_switch_failure(
|
||||
uint32_t gnb_ue_ngap_id, uint32_t amf_ue_ngap_id,
|
||||
NGAP_Cause_PR group, long cause);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_handover_command(gnb_ue_t *source_ue);
|
||||
ogs_pkbuf_t *ngap_build_handover_preparation_failure(
|
||||
gnb_ue_t *source_ue, NGAP_Cause_t *cause);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_handover_request(
|
||||
amf_ue_t *amf_ue, gnb_ue_t *target_ue,
|
||||
NGAP_ENB_UE_NGAP_ID_t *gnb_ue_ngap_id,
|
||||
NGAP_AMF_UE_NGAP_ID_t *amf_ue_ngap_id,
|
||||
NGAP_HandoverType_t *handovertype,
|
||||
NGAP_Cause_t *cause,
|
||||
NGAP_Source_ToTarget_TransparentContainer_t
|
||||
*source_totarget_transparentContainer);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_handover_cancel_ack(
|
||||
gnb_ue_t *source_ue);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_amf_status_transfer(
|
||||
gnb_ue_t *target_ue,
|
||||
NGAP_ENB_StatusTransfer_TransparentContainer_t
|
||||
*gnb_statustransfer_transparentContainer);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_error_indication(
|
||||
NGAP_AMF_UE_NGAP_ID_t *amf_ue_ngap_id,
|
||||
NGAP_ENB_UE_NGAP_ID_t *gnb_ue_ngap_id,
|
||||
NGAP_Cause_PR group, long cause);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_s1_reset(
|
||||
NGAP_Cause_PR group, long cause,
|
||||
NGAP_UE_associatedLogicalS1_ConnectionListRes_t *partOfS1_Interface);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_s1_reset_partial(
|
||||
NGAP_Cause_PR group, long cause,
|
||||
NGAP_AMF_UE_NGAP_ID_t *amf_ue_ngap_id,
|
||||
NGAP_ENB_UE_NGAP_ID_t *gnb_ue_ngap_id);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_s1_reset_ack(
|
||||
NGAP_UE_associatedLogicalS1_ConnectionListRes_t *partOfS1_Interface);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_write_replace_warning_request(
|
||||
sbc_pws_data_t *sbc_pws);
|
||||
|
||||
ogs_pkbuf_t *ngap_build_kill_request(sbc_pws_data_t *sbc_pws);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NGAP_BUILD_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NGAP_HANDLER_H
|
||||
#define NGAP_HANDLER_H
|
||||
|
||||
#include "context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ngap_handle_ng_setup_request(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
#if 0
|
||||
void ngap_handle_initial_ue_message(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
void ngap_handle_uplink_nas_transport(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
void ngap_handle_ue_capability_info_indication(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
void ngap_handle_initial_context_setup_response(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
void ngap_handle_initial_context_setup_failure(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
|
||||
void ngap_handle_ue_context_modification_response(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
void ngap_handle_ue_context_modification_failure(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
|
||||
void ngap_handle_ue_context_release_request(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
void ngap_handle_ue_context_release_complete(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
|
||||
void ngap_handle_e_rab_setup_response(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
|
||||
void ngap_handle_path_switch_request(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
|
||||
void ngap_handle_handover_required(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
void ngap_handle_handover_request_ack(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
void ngap_handle_handover_failure(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
void ngap_handle_handover_cancel(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
|
||||
void ngap_handle_gnb_status_transfer(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
void ngap_handle_gnb_configuration_transfer(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message, ogs_pkbuf_t *pkbuf);
|
||||
void ngap_handle_handover_notification(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
|
||||
void ngap_handle_s1_reset(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
|
||||
void ngap_handle_write_replace_warning_response(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
void ngap_handle_kill_response(
|
||||
amf_gnb_t *gnb, ogs_ngap_message_t *message);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NGAP_HANDLER_H */
|
|
@ -0,0 +1,546 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ogs-sctp.h"
|
||||
|
||||
#include "context.h"
|
||||
|
||||
#include "ngap-build.h"
|
||||
#include "ngap-path.h"
|
||||
|
||||
int ngap_open(void)
|
||||
{
|
||||
ogs_socknode_t *node = NULL;
|
||||
|
||||
ogs_list_for_each(&amf_self()->ngap_list, node)
|
||||
ngap_server(node);
|
||||
|
||||
ogs_list_for_each(&amf_self()->ngap_list6, node)
|
||||
ngap_server(node);
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
void ngap_close()
|
||||
{
|
||||
ogs_socknode_remove_all(&amf_self()->ngap_list);
|
||||
ogs_socknode_remove_all(&amf_self()->ngap_list6);
|
||||
}
|
||||
|
||||
int ngap_send(ogs_sock_t *sock, ogs_pkbuf_t *pkbuf,
|
||||
ogs_sockaddr_t *addr, uint16_t stream_no)
|
||||
{
|
||||
int sent;
|
||||
|
||||
ogs_assert(sock);
|
||||
ogs_assert(pkbuf);
|
||||
|
||||
sent = ogs_sctp_sendmsg(sock, pkbuf->data, pkbuf->len,
|
||||
addr, OGS_SCTP_NGAP_PPID, stream_no);
|
||||
if (sent < 0 || sent != pkbuf->len) {
|
||||
ogs_error("ogs_sctp_sendmsg error (%d:%s)", errno, strerror(errno));
|
||||
return OGS_ERROR;
|
||||
}
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
int ngap_send_to_gnb(amf_gnb_t *gnb, ogs_pkbuf_t *pkbuf, uint16_t stream_no)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
int rv;
|
||||
|
||||
ogs_assert(gnb);
|
||||
ogs_assert(pkbuf);
|
||||
ogs_assert(gnb->sock);
|
||||
|
||||
ogs_debug(" IP[%s] ENB_ID[%d]",
|
||||
OGS_ADDR(gnb->addr, buf), gnb->gnb_id);
|
||||
|
||||
rv = ngap_send(gnb->sock, pkbuf,
|
||||
gnb->sock_type == SOCK_STREAM ? NULL : gnb->addr,
|
||||
stream_no);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_error("ngap_send() failed");
|
||||
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
ngap_event_push(AMF_EVT_NGAP_LO_CONNREFUSED,
|
||||
gnb->sock, gnb->addr, NULL, 0, 0);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int ngap_send_to_gnb_ue(gnb_ue_t *gnb_ue, ogs_pkbuf_t *pkbuf)
|
||||
{
|
||||
amf_gnb_t *gnb = NULL;
|
||||
|
||||
ogs_assert(gnb_ue);
|
||||
gnb = gnb_ue->gnb;
|
||||
ogs_assert(gnb);
|
||||
|
||||
return ngap_send_to_gnb(gnb, pkbuf, gnb_ue->gnb_ostream_id);
|
||||
}
|
||||
|
||||
int ngap_delayed_send_to_gnb_ue(
|
||||
gnb_ue_t *gnb_ue, ogs_pkbuf_t *pkbuf, ogs_time_t duration)
|
||||
{
|
||||
ogs_assert(gnb_ue);
|
||||
ogs_assert(pkbuf);
|
||||
|
||||
if (duration) {
|
||||
amf_event_t *e = NULL;
|
||||
|
||||
e = amf_event_new(AMF_EVT_NGAP_TIMER);
|
||||
ogs_assert(e);
|
||||
e->timer = ogs_timer_add(
|
||||
amf_self()->timer_mgr, amf_timer_ng_delayed_send, e);
|
||||
ogs_assert(e->timer);
|
||||
e->pkbuf = pkbuf;
|
||||
e->gnb_ue = gnb_ue;
|
||||
e->gnb = gnb_ue->gnb;
|
||||
|
||||
ogs_timer_start(e->timer, duration);
|
||||
|
||||
return OGS_OK;
|
||||
} else {
|
||||
amf_gnb_t *gnb = NULL;
|
||||
gnb = gnb_ue->gnb;
|
||||
ogs_assert(gnb);
|
||||
return ngap_send_to_gnb_ue(gnb_ue, pkbuf);
|
||||
}
|
||||
}
|
||||
|
||||
int ngap_send_to_esm(amf_ue_t *amf_ue, ogs_pkbuf_t *esmbuf)
|
||||
{
|
||||
int rv;
|
||||
amf_event_t *e = NULL;
|
||||
|
||||
ogs_assert(amf_ue);
|
||||
ogs_assert(esmbuf);
|
||||
|
||||
e = amf_event_new(AMF_EVT_ESM_MESSAGE);
|
||||
ogs_assert(e);
|
||||
e->amf_ue = amf_ue;
|
||||
e->pkbuf = esmbuf;
|
||||
rv = ogs_queue_push(amf_self()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
|
||||
ogs_pkbuf_free(e->pkbuf);
|
||||
amf_event_free(e);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int ngap_send_to_nas(gnb_ue_t *gnb_ue,
|
||||
NGAP_ProcedureCode_t procedureCode, NGAP_NAS_PDU_t *nasPdu)
|
||||
{
|
||||
ogs_nas_eps_security_header_t *sh = NULL;
|
||||
ogs_nas_security_header_type_t security_header_type;
|
||||
|
||||
ogs_nas_emm_header_t *h = NULL;
|
||||
ogs_pkbuf_t *nasbuf = NULL;
|
||||
amf_event_t *e = NULL;
|
||||
|
||||
ogs_assert(gnb_ue);
|
||||
ogs_assert(nasPdu);
|
||||
|
||||
/* The Packet Buffer(pkbuf_t) for NAS message MUST make a HEADROOM.
|
||||
* When calculating AES_CMAC, we need to use the headroom of the packet. */
|
||||
nasbuf = ogs_pkbuf_alloc(NULL, OGS_NAS_HEADROOM+nasPdu->size);
|
||||
ogs_pkbuf_reserve(nasbuf, OGS_NAS_HEADROOM);
|
||||
ogs_pkbuf_put_data(nasbuf, nasPdu->buf, nasPdu->size);
|
||||
|
||||
sh = (ogs_nas_eps_security_header_t *)nasbuf->data;
|
||||
ogs_assert(sh);
|
||||
|
||||
memset(&security_header_type, 0, sizeof(ogs_nas_security_header_type_t));
|
||||
switch(sh->security_header_type) {
|
||||
case OGS_NAS_SECURITY_HEADER_PLAIN_NAS_MESSAGE:
|
||||
break;
|
||||
case OGS_NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE:
|
||||
security_header_type.service_request = 1;
|
||||
break;
|
||||
case OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED:
|
||||
security_header_type.integrity_protected = 1;
|
||||
ogs_pkbuf_pull(nasbuf, 6);
|
||||
break;
|
||||
case OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED:
|
||||
security_header_type.integrity_protected = 1;
|
||||
security_header_type.ciphered = 1;
|
||||
ogs_pkbuf_pull(nasbuf, 6);
|
||||
break;
|
||||
case OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_NEW_SECURITY_CONTEXT:
|
||||
security_header_type.integrity_protected = 1;
|
||||
security_header_type.new_security_context = 1;
|
||||
ogs_pkbuf_pull(nasbuf, 6);
|
||||
break;
|
||||
case OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHTERD_WITH_NEW_INTEGRITY_CONTEXT:
|
||||
security_header_type.integrity_protected = 1;
|
||||
security_header_type.ciphered = 1;
|
||||
security_header_type.new_security_context = 1;
|
||||
ogs_pkbuf_pull(nasbuf, 6);
|
||||
break;
|
||||
default:
|
||||
ogs_error("Not implemented(security header type:0x%x)",
|
||||
sh->security_header_type);
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
if (gnb_ue->amf_ue) {
|
||||
if (nas_eps_security_decode(gnb_ue->amf_ue,
|
||||
security_header_type, nasbuf) != OGS_OK) {
|
||||
ogs_error("nas_eps_security_decode failed()");
|
||||
return OGS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
h = (ogs_nas_emm_header_t *)nasbuf->data;
|
||||
ogs_assert(h);
|
||||
if (h->protocol_discriminator == OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM) {
|
||||
int rv;
|
||||
e = amf_event_new(AMF_EVT_EMM_MESSAGE);
|
||||
ogs_assert(e);
|
||||
e->gnb_ue = gnb_ue;
|
||||
e->ngap_code = procedureCode;
|
||||
e->nas_type = security_header_type.type;
|
||||
e->pkbuf = nasbuf;
|
||||
rv = ogs_queue_push(amf_self()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
|
||||
ogs_pkbuf_free(e->pkbuf);
|
||||
amf_event_free(e);
|
||||
}
|
||||
return rv;
|
||||
} else if (h->protocol_discriminator == OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM) {
|
||||
amf_ue_t *amf_ue = gnb_ue->amf_ue;
|
||||
ogs_assert(amf_ue);
|
||||
return ngap_send_to_esm(amf_ue, nasbuf);
|
||||
} else {
|
||||
ogs_error("Unknown/Unimplemented NAS Protocol discriminator 0x%02x",
|
||||
h->protocol_discriminator);
|
||||
return OGS_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void ngap_send_ng_setup_response(amf_gnb_t *gnb)
|
||||
{
|
||||
ogs_pkbuf_t *ngap_buffer;
|
||||
|
||||
ogs_debug("[AMF] NG-Setup response");
|
||||
ngap_buffer = ngap_build_setup_rsp();
|
||||
ogs_expect_or_return(ngap_buffer);
|
||||
|
||||
ogs_expect(OGS_OK ==
|
||||
ngap_send_to_gnb(gnb, ngap_buffer, NGAP_NON_UE_SIGNALLING));
|
||||
}
|
||||
|
||||
void ngap_send_ng_setup_failure(
|
||||
amf_gnb_t *gnb, NGAP_Cause_PR group, long cause)
|
||||
{
|
||||
ogs_pkbuf_t *ngap_buffer;
|
||||
|
||||
ogs_debug("[AMF] NG-Setup failure");
|
||||
ngap_buffer = ngap_build_setup_failure(group, cause, NGAP_TimeToWait_v10s);
|
||||
ogs_expect_or_return(ngap_buffer);
|
||||
|
||||
ogs_expect(OGS_OK ==
|
||||
ngap_send_to_gnb(gnb, ngap_buffer, NGAP_NON_UE_SIGNALLING));
|
||||
}
|
||||
|
||||
#if 0
|
||||
void ngap_send_initial_context_setup_request(amf_ue_t *amf_ue)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(amf_ue);
|
||||
|
||||
ngapbuf = ngap_build_initial_context_setup_request(amf_ue, NULL);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = nas_eps_send_to_gnb(amf_ue, ngapbuf);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
void ngap_send_ue_context_modification_request(amf_ue_t *amf_ue)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(amf_ue);
|
||||
|
||||
ngapbuf = ngap_build_ue_context_modification_request(amf_ue);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = nas_eps_send_to_gnb(amf_ue, ngapbuf);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
void ngap_send_ue_context_release_command(
|
||||
gnb_ue_t *gnb_ue, NGAP_Cause_PR group, long cause,
|
||||
uint8_t action, uint32_t delay)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(gnb_ue);
|
||||
|
||||
ogs_debug("[AMF] UE Context release command");
|
||||
ogs_debug(" ENB_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%d]",
|
||||
gnb_ue->gnb_ue_ngap_id, gnb_ue->amf_ue_ngap_id);
|
||||
|
||||
if (delay) {
|
||||
ogs_assert(action != NGAP_UE_CTX_REL_INVALID_ACTION);
|
||||
gnb_ue->ue_ctx_rel_action = action;
|
||||
|
||||
ogs_debug(" Group[%d] Cause[%d] Action[%d] Delay[%d]",
|
||||
group, (int)cause, action, delay);
|
||||
|
||||
ngapbuf = ngap_build_ue_context_release_command(gnb_ue, group, cause);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_delayed_send_to_gnb_ue(gnb_ue, ngapbuf, delay);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
} else {
|
||||
ogs_assert(action != NGAP_UE_CTX_REL_INVALID_ACTION);
|
||||
gnb_ue->ue_ctx_rel_action = action;
|
||||
|
||||
ogs_debug(" Group[%d] Cause[%d] Action[%d] Delay[%d]",
|
||||
group, (int)cause, action, delay);
|
||||
|
||||
ngapbuf = ngap_build_ue_context_release_command(gnb_ue, group, cause);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_delayed_send_to_gnb_ue(gnb_ue, ngapbuf, 0);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
}
|
||||
|
||||
void ngap_send_paging(amf_ue_t *amf_ue, NGAP_CNDomain_t cn_domain)
|
||||
{
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
amf_gnb_t *gnb = NULL;
|
||||
int i;
|
||||
int rv;
|
||||
|
||||
/* Find enB with matched TAI */
|
||||
ogs_list_for_each(&amf_self()->gnb_list, gnb) {
|
||||
for (i = 0; i < gnb->num_of_supported_ta_list; i++) {
|
||||
|
||||
if (memcmp(&gnb->supported_ta_list[i], &amf_ue->tai,
|
||||
sizeof(ogs_5gs_tai_t)) == 0) {
|
||||
|
||||
if (amf_ue->t3413.pkbuf) {
|
||||
ngapbuf = amf_ue->t3413.pkbuf;
|
||||
} else {
|
||||
ngapbuf = ngap_build_paging(amf_ue, cn_domain);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
}
|
||||
|
||||
amf_ue->t3413.pkbuf = ogs_pkbuf_copy(ngapbuf);
|
||||
|
||||
rv = ngap_send_to_gnb(gnb, ngapbuf, NGAP_NON_UE_SIGNALLING);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Start T3413 */
|
||||
ogs_timer_start(amf_ue->t3413.timer,
|
||||
amf_timer_cfg(AMF_TIMER_T3413)->duration);
|
||||
}
|
||||
|
||||
void ngap_send_amf_configuration_transfer(
|
||||
amf_gnb_t *target_gnb,
|
||||
NGAP_SONConfigurationTransfer_t *SONConfigurationTransfer)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(target_gnb);
|
||||
ogs_assert(SONConfigurationTransfer);
|
||||
|
||||
ngapbuf = ngap_build_amf_configuration_transfer(SONConfigurationTransfer);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_send_to_gnb(target_gnb, ngapbuf, NGAP_NON_UE_SIGNALLING);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
void ngap_send_path_switch_ack(amf_ue_t *amf_ue)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(amf_ue);
|
||||
|
||||
ngapbuf = ngap_build_path_switch_ack(amf_ue);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = nas_eps_send_to_gnb(amf_ue, ngapbuf);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
void ngap_send_handover_command(gnb_ue_t *source_ue)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(source_ue);
|
||||
|
||||
ngapbuf = ngap_build_handover_command(source_ue);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_send_to_gnb_ue(source_ue, ngapbuf);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
void ngap_send_handover_preparation_failure(
|
||||
gnb_ue_t *source_ue, NGAP_Cause_t *cause)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(source_ue);
|
||||
ogs_assert(cause);
|
||||
|
||||
ngapbuf = ngap_build_handover_preparation_failure(source_ue, cause);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_send_to_gnb_ue(source_ue, ngapbuf);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
void ngap_send_handover_cancel_ack(gnb_ue_t *source_ue)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(source_ue);
|
||||
|
||||
ngapbuf = ngap_build_handover_cancel_ack(source_ue);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_send_to_gnb_ue(source_ue, ngapbuf);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
|
||||
void ngap_send_handover_request(
|
||||
amf_ue_t *amf_ue,
|
||||
amf_gnb_t *target_gnb,
|
||||
NGAP_ENB_UE_NGAP_ID_t *gnb_ue_ngap_id,
|
||||
NGAP_AMF_UE_NGAP_ID_t *amf_ue_ngap_id,
|
||||
NGAP_HandoverType_t *handovertype,
|
||||
NGAP_Cause_t *cause,
|
||||
NGAP_Source_ToTarget_TransparentContainer_t
|
||||
*source_totarget_transparentContainer)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
gnb_ue_t *source_ue = NULL, *target_ue = NULL;
|
||||
|
||||
ogs_debug("[AMF] Handover request");
|
||||
|
||||
ogs_assert(target_gnb);
|
||||
|
||||
ogs_assert(amf_ue);
|
||||
source_ue = amf_ue->gnb_ue;
|
||||
ogs_assert(source_ue);
|
||||
ogs_assert(source_ue->target_ue == NULL);
|
||||
|
||||
target_ue = gnb_ue_add(target_gnb, INVALID_UE_NGAP_ID);
|
||||
ogs_assert(target_ue);
|
||||
|
||||
ogs_debug(" Source : ENB_UE_NGAP_ID[%d] AMF_UE_NGAP_ID[%d]",
|
||||
source_ue->gnb_ue_ngap_id, source_ue->amf_ue_ngap_id);
|
||||
ogs_debug(" Target : ENB_UE_NGAP_ID[Unknown] AMF_UE_NGAP_ID[%d]",
|
||||
target_ue->amf_ue_ngap_id);
|
||||
|
||||
source_ue_associate_target_ue(source_ue, target_ue);
|
||||
|
||||
ngapbuf = ngap_build_handover_request(amf_ue, target_ue,
|
||||
gnb_ue_ngap_id, amf_ue_ngap_id,
|
||||
handovertype, cause,
|
||||
source_totarget_transparentContainer);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_send_to_gnb_ue(target_ue, ngapbuf);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
void ngap_send_amf_status_transfer(
|
||||
gnb_ue_t *target_ue,
|
||||
NGAP_ENB_StatusTransfer_TransparentContainer_t
|
||||
*gnb_statustransfer_transparentContainer)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(target_ue);
|
||||
|
||||
ngapbuf = ngap_build_amf_status_transfer(target_ue,
|
||||
gnb_statustransfer_transparentContainer);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_send_to_gnb_ue(target_ue, ngapbuf);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
void ngap_send_error_indication(
|
||||
amf_gnb_t *gnb,
|
||||
NGAP_AMF_UE_NGAP_ID_t *amf_ue_ngap_id,
|
||||
NGAP_ENB_UE_NGAP_ID_t *gnb_ue_ngap_id,
|
||||
NGAP_Cause_PR group, long cause)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(gnb);
|
||||
|
||||
ngapbuf = ngap_build_error_indication(
|
||||
amf_ue_ngap_id, gnb_ue_ngap_id, group, cause);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_send_to_gnb(gnb, ngapbuf, NGAP_NON_UE_SIGNALLING);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
|
||||
void ngap_send_ng_reset_ack(
|
||||
amf_gnb_t *gnb,
|
||||
NGAP_UE_associatedLogicalNG_ConnectionListRes_t *partOfNG_Interface)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *ngapbuf = NULL;
|
||||
|
||||
ogs_assert(gnb);
|
||||
|
||||
ngapbuf = ngap_build_ng_reset_ack(partOfNG_Interface);
|
||||
ogs_expect_or_return(ngapbuf);
|
||||
|
||||
rv = ngap_send_to_gnb(gnb, ngapbuf, NGAP_NON_UE_SIGNALLING);
|
||||
ogs_expect(rv == OGS_OK);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NGAP_PATH_H
|
||||
#define NGAP_PATH_H
|
||||
|
||||
#include "context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NGAP_NON_UE_SIGNALLING 0
|
||||
|
||||
#define ngap_event_push amf_sctp_event_push
|
||||
|
||||
int ngap_open(void);
|
||||
void ngap_close(void);
|
||||
|
||||
ogs_sock_t *ngap_server(ogs_socknode_t *node);
|
||||
void ngap_recv_upcall(short when, ogs_socket_t fd, void *data);
|
||||
int ngap_send(ogs_sock_t *sock,
|
||||
ogs_pkbuf_t *pkbuf, ogs_sockaddr_t *addr, uint16_t stream_no);
|
||||
|
||||
int ngap_send_to_gnb(
|
||||
amf_gnb_t *gnb, ogs_pkbuf_t *pkb, uint16_t stream_no);
|
||||
#if 0
|
||||
int ngap_send_to_gnb_ue(gnb_ue_t *gnb_ue, ogs_pkbuf_t *pkbuf);
|
||||
int ngap_delayed_send_to_gnb_ue(gnb_ue_t *gnb_ue,
|
||||
ogs_pkbuf_t *pkbuf, ogs_time_t duration);
|
||||
int ngap_send_to_nas(gnb_ue_t *gnb_ue,
|
||||
NGAP_ProcedureCode_t procedureCode, NGAP_NAS_PDU_t *nasPdu);
|
||||
int ngap_send_to_esm(amf_ue_t *amf_ue, ogs_pkbuf_t *esmbuf);
|
||||
#endif
|
||||
|
||||
void ngap_send_ng_setup_response(amf_gnb_t *gnb);
|
||||
void ngap_send_ng_setup_failure(
|
||||
amf_gnb_t *gnb, NGAP_Cause_PR group, long cause);
|
||||
|
||||
#if 0
|
||||
void ngap_send_initial_context_setup_request(amf_ue_t *amf_ue);
|
||||
void ngap_send_ue_context_modification_request(amf_ue_t *amf_ue);
|
||||
void ngap_send_ue_context_release_command(
|
||||
gnb_ue_t *gnb_ue, NGAP_Cause_PR group, long cause,
|
||||
uint8_t action, uint32_t delay);
|
||||
|
||||
void ngap_send_paging(amf_ue_t *amf_ue, NGAP_CNDomain_t cn_domain);
|
||||
|
||||
void ngap_send_amf_configuration_transfer(
|
||||
amf_gnb_t *target_gnb,
|
||||
NGAP_SONConfigurationTransfer_t *SONConfigurationTransfer);
|
||||
|
||||
void ngap_send_path_switch_ack(amf_ue_t *amf_ue);
|
||||
|
||||
void ngap_send_handover_command(gnb_ue_t *source_ue);
|
||||
void ngap_send_handover_preparation_failure(
|
||||
gnb_ue_t *source_ue, NGAP_Cause_t *cause);
|
||||
|
||||
void ngap_send_handover_request(
|
||||
amf_ue_t *amf_ue,
|
||||
amf_gnb_t *target_gnb,
|
||||
NGAP_ENB_UE_NGAP_ID_t *gnb_ue_ngap_id,
|
||||
NGAP_AMF_UE_NGAP_ID_t *amf_ue_ngap_id,
|
||||
NGAP_HandoverType_t *handovertype,
|
||||
NGAP_Cause_t *cause,
|
||||
NGAP_Source_ToTarget_TransparentContainer_t
|
||||
*source_totarget_transparentContainer);
|
||||
|
||||
void ngap_send_handover_cancel_ack(gnb_ue_t *source_ue);
|
||||
|
||||
void ngap_send_amf_status_transfer(
|
||||
gnb_ue_t *target_ue,
|
||||
NGAP_ENB_StatusTransfer_TransparentContainer_t
|
||||
*gnb_statustransfer_transparentContainer);
|
||||
void ngap_send_error_indication(
|
||||
amf_gnb_t *gnb,
|
||||
NGAP_AMF_UE_NGAP_ID_t *amf_ue_ngap_id,
|
||||
NGAP_ENB_UE_NGAP_ID_t *gnb_ue_ngap_id,
|
||||
NGAP_Cause_PR group, long cause);
|
||||
void ngap_send_ng_reset_ack(
|
||||
amf_gnb_t *gnb,
|
||||
NGAP_UE_associatedLogicalNG_ConnectionListRes_t *partOfNG_Interface);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NGAP_PATH_H */
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ogs-sctp.h"
|
||||
|
||||
#include "ngap-path.h"
|
||||
|
||||
#if HAVE_USRSCTP
|
||||
static void usrsctp_recv_handler(struct socket *socket, void *data, int flags);
|
||||
#else
|
||||
static void lksctp_accept_handler(short when, ogs_socket_t fd, void *data);
|
||||
#endif
|
||||
|
||||
void ngap_accept_handler(ogs_sock_t *sock);
|
||||
void ngap_recv_handler(ogs_sock_t *sock);
|
||||
|
||||
ogs_sock_t *ngap_server(ogs_socknode_t *node)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
ogs_sock_t *sock = NULL;
|
||||
|
||||
ogs_assert(node);
|
||||
|
||||
ogs_socknode_sctp_option(node, &ogs_config()->sockopt);
|
||||
ogs_socknode_nodelay(node, true);
|
||||
|
||||
#if HAVE_USRSCTP
|
||||
sock = ogs_sctp_server(SOCK_SEQPACKET, node);
|
||||
ogs_assert(sock);
|
||||
usrsctp_set_non_blocking((struct socket *)sock, 1);
|
||||
usrsctp_set_upcall((struct socket *)sock, usrsctp_recv_handler, NULL);
|
||||
#else
|
||||
sock = ogs_sctp_server(SOCK_STREAM, node);
|
||||
ogs_assert(sock);
|
||||
node->poll = ogs_pollset_add(amf_self()->pollset,
|
||||
OGS_POLLIN, sock->fd, lksctp_accept_handler, sock);
|
||||
#endif
|
||||
|
||||
ogs_info("ngap_server() [%s]:%d",
|
||||
OGS_ADDR(node->addr, buf), OGS_PORT(node->addr));
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
void ngap_recv_upcall(short when, ogs_socket_t fd, void *data)
|
||||
{
|
||||
ogs_sock_t *sock = NULL;
|
||||
|
||||
ogs_assert(fd != INVALID_SOCKET);
|
||||
sock = data;
|
||||
ogs_assert(sock);
|
||||
|
||||
ngap_recv_handler(sock);
|
||||
}
|
||||
|
||||
#if HAVE_USRSCTP
|
||||
static void usrsctp_recv_handler(struct socket *socket, void *data, int flags)
|
||||
{
|
||||
int events;
|
||||
|
||||
while ((events = usrsctp_get_events(socket)) &&
|
||||
(events & SCTP_EVENT_READ)) {
|
||||
ngap_recv_handler((ogs_sock_t *)socket);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void lksctp_accept_handler(short when, ogs_socket_t fd, void *data)
|
||||
{
|
||||
ogs_assert(data);
|
||||
ogs_assert(fd != INVALID_SOCKET);
|
||||
|
||||
ngap_accept_handler(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ngap_accept_handler(ogs_sock_t *sock)
|
||||
{
|
||||
char buf[OGS_ADDRSTRLEN];
|
||||
ogs_sock_t *new = NULL;
|
||||
|
||||
ogs_assert(sock);
|
||||
|
||||
new = ogs_sock_accept(sock);
|
||||
if (new) {
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
|
||||
addr = ogs_calloc(1, sizeof(ogs_sockaddr_t));
|
||||
ogs_assert(addr);
|
||||
memcpy(addr, &new->remote_addr, sizeof(ogs_sockaddr_t));
|
||||
|
||||
ogs_info("eNB-S1 accepted[%s]:%d in s1_path module",
|
||||
OGS_ADDR(addr, buf), OGS_PORT(addr));
|
||||
|
||||
ngap_event_push(AMF_EVT_NGAP_LO_ACCEPT,
|
||||
new, addr, NULL, 0, 0);
|
||||
} else {
|
||||
ogs_log_message(OGS_LOG_ERROR, ogs_socket_errno, "accept() failed");
|
||||
}
|
||||
}
|
||||
|
||||
void ngap_recv_handler(ogs_sock_t *sock)
|
||||
{
|
||||
ogs_pkbuf_t *pkbuf;
|
||||
int size;
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
ogs_sockaddr_t from;
|
||||
ogs_sctp_info_t sinfo;
|
||||
int flags = 0;
|
||||
|
||||
ogs_assert(sock);
|
||||
|
||||
pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
||||
ogs_pkbuf_put(pkbuf, OGS_MAX_SDU_LEN);
|
||||
size = ogs_sctp_recvmsg(
|
||||
sock, pkbuf->data, pkbuf->len, &from, &sinfo, &flags);
|
||||
if (size < 0) {
|
||||
ogs_error("ogs_sctp_recvmsg(%d) failed(%d:%s)",
|
||||
size, errno, strerror(errno));
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & MSG_NOTIFICATION) {
|
||||
union sctp_notification *not =
|
||||
(union sctp_notification *)pkbuf->data;
|
||||
|
||||
switch(not->sn_header.sn_type) {
|
||||
case SCTP_ASSOC_CHANGE :
|
||||
ogs_debug("SCTP_ASSOC_CHANGE:"
|
||||
"[T:%d, F:0x%x, S:%d, I/O:%d/%d]",
|
||||
not->sn_assoc_change.sac_type,
|
||||
not->sn_assoc_change.sac_flags,
|
||||
not->sn_assoc_change.sac_state,
|
||||
not->sn_assoc_change.sac_inbound_streams,
|
||||
not->sn_assoc_change.sac_outbound_streams);
|
||||
|
||||
if (not->sn_assoc_change.sac_state == SCTP_COMM_UP) {
|
||||
ogs_debug("SCTP_COMM_UP");
|
||||
|
||||
addr = ogs_calloc(1, sizeof(ogs_sockaddr_t));
|
||||
ogs_assert(addr);
|
||||
memcpy(addr, &from, sizeof(ogs_sockaddr_t));
|
||||
|
||||
ngap_event_push(AMF_EVT_NGAP_LO_SCTP_COMM_UP,
|
||||
sock, addr, NULL,
|
||||
not->sn_assoc_change.sac_inbound_streams,
|
||||
not->sn_assoc_change.sac_outbound_streams);
|
||||
} else if (not->sn_assoc_change.sac_state == SCTP_SHUTDOWN_COMP ||
|
||||
not->sn_assoc_change.sac_state == SCTP_COMM_LOST) {
|
||||
|
||||
if (not->sn_assoc_change.sac_state == SCTP_SHUTDOWN_COMP)
|
||||
ogs_debug("SCTP_SHUTDOWN_COMP");
|
||||
if (not->sn_assoc_change.sac_state == SCTP_COMM_LOST)
|
||||
ogs_debug("SCTP_COMM_LOST");
|
||||
|
||||
addr = ogs_calloc(1, sizeof(ogs_sockaddr_t));
|
||||
ogs_assert(addr);
|
||||
memcpy(addr, &from, sizeof(ogs_sockaddr_t));
|
||||
|
||||
ngap_event_push(AMF_EVT_NGAP_LO_CONNREFUSED,
|
||||
sock, addr, NULL, 0, 0);
|
||||
}
|
||||
break;
|
||||
case SCTP_SHUTDOWN_EVENT :
|
||||
case SCTP_SEND_FAILED :
|
||||
if (not->sn_header.sn_type == SCTP_SHUTDOWN_EVENT)
|
||||
ogs_debug("SCTP_SHUTDOWN_EVENT:[T:%d, F:0x%x, L:%d]",
|
||||
not->sn_shutdown_event.sse_type,
|
||||
not->sn_shutdown_event.sse_flags,
|
||||
not->sn_shutdown_event.sse_length);
|
||||
if (not->sn_header.sn_type == SCTP_SEND_FAILED)
|
||||
#if HAVE_USRSCTP
|
||||
ogs_error("SCTP_SEND_FAILED:[T:%d, F:0x%x, S:%d]",
|
||||
not->sn_send_failed_event.ssfe_type,
|
||||
not->sn_send_failed_event.ssfe_flags,
|
||||
not->sn_send_failed_event.ssfe_error);
|
||||
#else
|
||||
ogs_error("SCTP_SEND_FAILED:[T:%d, F:0x%x, S:%d]",
|
||||
not->sn_send_failed.ssf_type,
|
||||
not->sn_send_failed.ssf_flags,
|
||||
not->sn_send_failed.ssf_error);
|
||||
#endif
|
||||
|
||||
addr = ogs_calloc(1, sizeof(ogs_sockaddr_t));
|
||||
ogs_assert(addr);
|
||||
memcpy(addr, &from, sizeof(ogs_sockaddr_t));
|
||||
|
||||
ngap_event_push(AMF_EVT_NGAP_LO_CONNREFUSED,
|
||||
sock, addr, NULL, 0, 0);
|
||||
break;
|
||||
case SCTP_PEER_ADDR_CHANGE:
|
||||
ogs_warn("SCTP_PEER_ADDR_CHANGE:[T:%d, F:0x%x, S:%d]",
|
||||
not->sn_paddr_change.spc_type,
|
||||
not->sn_paddr_change.spc_flags,
|
||||
not->sn_paddr_change.spc_error);
|
||||
break;
|
||||
case SCTP_REMOTE_ERROR:
|
||||
ogs_warn("SCTP_REMOTE_ERROR:[T:%d, F:0x%x, S:%d]",
|
||||
not->sn_remote_error.sre_type,
|
||||
not->sn_remote_error.sre_flags,
|
||||
not->sn_remote_error.sre_error);
|
||||
break;
|
||||
default :
|
||||
ogs_error("Discarding event with unknown flags:0x%x type:0x%x",
|
||||
flags, not->sn_header.sn_type);
|
||||
break;
|
||||
}
|
||||
} else if (flags & MSG_EOR) {
|
||||
ogs_pkbuf_trim(pkbuf, size);
|
||||
|
||||
addr = ogs_calloc(1, sizeof(ogs_sockaddr_t));
|
||||
ogs_assert(addr);
|
||||
memcpy(addr, &from, sizeof(ogs_sockaddr_t));
|
||||
|
||||
ngap_event_push(AMF_EVT_NGAP_MESSAGE, sock, addr, pkbuf, 0, 0);
|
||||
return;
|
||||
} else {
|
||||
ogs_assert_if_reached();
|
||||
}
|
||||
|
||||
ogs_pkbuf_free(pkbuf);
|
||||
}
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ngap-build.h"
|
||||
#include "ngap-handler.h"
|
||||
#include "ngap-path.h"
|
||||
|
||||
void ngap_state_initial(ogs_fsm_t *s, amf_event_t *e)
|
||||
{
|
||||
ogs_assert(s);
|
||||
|
||||
amf_sm_debug(e);
|
||||
|
||||
OGS_FSM_TRAN(s, &ngap_state_operational);
|
||||
}
|
||||
|
||||
void ngap_state_final(ogs_fsm_t *s, amf_event_t *e)
|
||||
{
|
||||
ogs_assert(s);
|
||||
|
||||
amf_sm_debug(e);
|
||||
}
|
||||
|
||||
void ngap_state_operational(ogs_fsm_t *s, amf_event_t *e)
|
||||
{
|
||||
amf_gnb_t *gnb = NULL;
|
||||
#if 0
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
#endif
|
||||
|
||||
NGAP_NGAP_PDU_t *pdu = NULL;
|
||||
NGAP_InitiatingMessage_t *initiatingMessage = NULL;
|
||||
NGAP_SuccessfulOutcome_t *successfulOutcome = NULL;
|
||||
NGAP_UnsuccessfulOutcome_t *unsuccessfulOutcome = NULL;
|
||||
|
||||
ogs_assert(s);
|
||||
ogs_assert(e);
|
||||
|
||||
amf_sm_debug(e);
|
||||
|
||||
gnb = e->gnb;
|
||||
ogs_assert(gnb);
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
break;
|
||||
case OGS_FSM_EXIT_SIG:
|
||||
break;
|
||||
case AMF_EVT_NGAP_MESSAGE:
|
||||
pdu = e->ngap.message;
|
||||
ogs_assert(pdu);
|
||||
|
||||
switch (pdu->present) {
|
||||
case NGAP_NGAP_PDU_PR_initiatingMessage :
|
||||
initiatingMessage = pdu->choice.initiatingMessage;
|
||||
ogs_assert(initiatingMessage);
|
||||
|
||||
switch (initiatingMessage->procedureCode) {
|
||||
case NGAP_ProcedureCode_id_NGSetup :
|
||||
ngap_handle_ng_setup_request(gnb, pdu);
|
||||
break;
|
||||
#if 0
|
||||
case NGAP_ProcedureCode_id_initialUEMessage :
|
||||
ngap_handle_initial_ue_message(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_uplinkNASTransport :
|
||||
ngap_handle_uplink_nas_transport(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_UECapabilityInfoIndication :
|
||||
ngap_handle_ue_capability_info_indication( gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_UEContextReleaseRequest:
|
||||
ngap_handle_ue_context_release_request( gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_PathSwitchRequest:
|
||||
ngap_handle_path_switch_request(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_eNBConfigurationTransfer:
|
||||
pkbuf = e->pkbuf;
|
||||
ogs_assert(pkbuf);
|
||||
|
||||
ngap_handle_gnb_configuration_transfer(gnb, pdu, pkbuf);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_HandoverPreparation:
|
||||
ngap_handle_handover_required(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_HandoverCancel:
|
||||
ngap_handle_handover_cancel(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_eNBStatusTransfer:
|
||||
ngap_handle_gnb_status_transfer(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_HandoverNotification:
|
||||
ngap_handle_handover_notification(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_Reset:
|
||||
ngap_handle_s1_reset(gnb, pdu);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ogs_warn("Not implemented(choice:%d, proc:%d)",
|
||||
pdu->present, (int)initiatingMessage->procedureCode);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NGAP_NGAP_PDU_PR_successfulOutcome :
|
||||
successfulOutcome = pdu->choice.successfulOutcome;
|
||||
ogs_assert(successfulOutcome);
|
||||
|
||||
switch (successfulOutcome->procedureCode) {
|
||||
#if 0
|
||||
case NGAP_ProcedureCode_id_InitialContextSetup:
|
||||
ngap_handle_initial_context_setup_response(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_UEContextModification:
|
||||
ngap_handle_ue_context_modification_response(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_UEContextRelease:
|
||||
ngap_handle_ue_context_release_complete(
|
||||
gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_E_RABSetup:
|
||||
ngap_handle_e_rab_setup_response(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_E_RABModify:
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_E_RABRelease:
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_HandoverResourceAllocation:
|
||||
ngap_handle_handover_request_ack(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_WriteReplaceWarning:
|
||||
ngap_handle_write_replace_warning_response(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_Kill:
|
||||
ngap_handle_kill_response(gnb, pdu);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ogs_warn("Not implemented(choice:%d, proc:%d)",
|
||||
pdu->present, (int)successfulOutcome->procedureCode);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case NGAP_NGAP_PDU_PR_unsuccessfulOutcome :
|
||||
unsuccessfulOutcome = pdu->choice.unsuccessfulOutcome;
|
||||
ogs_assert(unsuccessfulOutcome);
|
||||
|
||||
switch (unsuccessfulOutcome->procedureCode) {
|
||||
#if 0
|
||||
case NGAP_ProcedureCode_id_InitialContextSetup :
|
||||
ngap_handle_initial_context_setup_failure(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_UEContextModification:
|
||||
ngap_handle_ue_context_modification_failure(gnb, pdu);
|
||||
break;
|
||||
case NGAP_ProcedureCode_id_HandoverResourceAllocation :
|
||||
ngap_handle_handover_failure(gnb, pdu);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ogs_warn("Not implemented(choice:%d, proc:%d)",
|
||||
pdu->present, (int)unsuccessfulOutcome->procedureCode);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ogs_warn("Not implemented(choice:%d)", pdu->present);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case AMF_EVT_NGAP_TIMER:
|
||||
switch (e->timer_id) {
|
||||
#if 0
|
||||
case AMF_TIMER_S1_DELAYED_SEND:
|
||||
ogs_assert(e->gnb_ue);
|
||||
ogs_assert(e->pkbuf);
|
||||
|
||||
ogs_expect(OGS_OK == ngap_send_to_gnb_ue(e->gnb_ue, e->pkbuf));
|
||||
ogs_timer_delete(e->timer);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ogs_error("Unknown timer[%s:%d]",
|
||||
amf_timer_get_name(e->timer_id), e->timer_id);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ogs_error("Unknown event %s", amf_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ngap_state_exception(ogs_fsm_t *s, amf_event_t *e)
|
||||
{
|
||||
ogs_assert(s);
|
||||
ogs_assert(e);
|
||||
|
||||
amf_sm_debug(e);
|
||||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
break;
|
||||
case OGS_FSM_EXIT_SIG:
|
||||
break;
|
||||
default:
|
||||
ogs_error("Unknown event %s", amf_event_get_name(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "nnrf-build.h"
|
||||
|
||||
ogs_sbi_request_t *amf_nnrf_build_nf_register(
|
||||
ogs_sbi_nf_instance_t *nf_instance)
|
||||
{
|
||||
ogs_sbi_message_t message;
|
||||
ogs_sbi_request_t *request = NULL;
|
||||
ogs_sbi_client_t *client = NULL;
|
||||
|
||||
OpenAPI_nf_profile_t *NFProfile = NULL;
|
||||
|
||||
ogs_assert(nf_instance);
|
||||
client = nf_instance->client;
|
||||
ogs_assert(client);
|
||||
|
||||
memset(&message, 0, sizeof(message));
|
||||
message.h.method = (char *)OGS_SBI_HTTP_METHOD_PUT;
|
||||
message.h.service.name = (char *)OGS_SBI_SERVICE_NAME_NRF_NFM;
|
||||
message.h.api.version = (char *)OGS_SBI_API_VERSION;
|
||||
message.h.resource.name = (char *)OGS_SBI_RESOURCE_NAME_NF_INSTANCES;
|
||||
message.h.resource.id = ogs_sbi_self()->nf_instance_id;
|
||||
|
||||
message.http.content_encoding = (char*)ogs_sbi_self()->content_encoding;
|
||||
|
||||
NFProfile = ogs_sbi_nnrf_build_nf_profile(nf_instance);
|
||||
ogs_assert(NFProfile);
|
||||
|
||||
NFProfile->heart_beat_timer = nf_instance->time.heartbeat;
|
||||
|
||||
message.NFProfile = NFProfile;
|
||||
|
||||
request = ogs_sbi_build_request(&message);
|
||||
ogs_assert(request);
|
||||
|
||||
ogs_sbi_nnrf_free_nf_profile(NFProfile);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
ogs_sbi_request_t *amf_nnrf_build_nf_update(ogs_sbi_nf_instance_t *nf_instance)
|
||||
{
|
||||
ogs_sbi_message_t message;
|
||||
ogs_sbi_request_t *request = NULL;
|
||||
|
||||
OpenAPI_list_t *PatchItemList;
|
||||
OpenAPI_patch_item_t item;
|
||||
|
||||
ogs_assert(nf_instance);
|
||||
|
||||
memset(&message, 0, sizeof(message));
|
||||
message.h.method = (char *)OGS_SBI_HTTP_METHOD_PATCH;
|
||||
message.h.service.name = (char *)OGS_SBI_SERVICE_NAME_NRF_NFM;
|
||||
message.h.api.version = (char *)OGS_SBI_API_VERSION;
|
||||
message.h.resource.name = (char *)OGS_SBI_RESOURCE_NAME_NF_INSTANCES;
|
||||
message.h.resource.id = ogs_sbi_self()->nf_instance_id;
|
||||
message.http.content_type = (char *)OGS_SBI_CONTENT_PATCH_TYPE;
|
||||
|
||||
PatchItemList = OpenAPI_list_create();
|
||||
ogs_assert(PatchItemList);
|
||||
|
||||
memset(&item, 0, sizeof(item));
|
||||
item.op = OpenAPI_patch_operation_replace;
|
||||
item.path = (char *)"/nfStatus";
|
||||
item.value = OpenAPI_nf_status_ToString(OpenAPI_nf_status_REGISTERED);
|
||||
|
||||
OpenAPI_list_add(PatchItemList, &item);
|
||||
|
||||
message.PatchItemList = PatchItemList;
|
||||
|
||||
request = ogs_sbi_build_request(&message);
|
||||
ogs_assert(request);
|
||||
|
||||
OpenAPI_list_free(PatchItemList);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
ogs_sbi_request_t *amf_nnrf_build_nf_de_register(
|
||||
ogs_sbi_nf_instance_t *nf_instance)
|
||||
{
|
||||
ogs_sbi_message_t message;
|
||||
ogs_sbi_request_t *request = NULL;
|
||||
|
||||
ogs_assert(nf_instance);
|
||||
|
||||
memset(&message, 0, sizeof(message));
|
||||
message.h.method = (char *)OGS_SBI_HTTP_METHOD_DELETE;
|
||||
message.h.service.name = (char *)OGS_SBI_SERVICE_NAME_NRF_NFM;
|
||||
message.h.api.version = (char *)OGS_SBI_API_VERSION;
|
||||
message.h.resource.name = (char *)OGS_SBI_RESOURCE_NAME_NF_INSTANCES;
|
||||
message.h.resource.id = nf_instance->id;
|
||||
|
||||
request = ogs_sbi_build_request(&message);
|
||||
ogs_assert(request);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
ogs_sbi_request_t *amf_nnrf_build_nf_status_subscribe(
|
||||
ogs_sbi_subscription_t *subscription)
|
||||
{
|
||||
ogs_sbi_message_t message;
|
||||
ogs_sbi_request_t *request = NULL;
|
||||
ogs_sbi_server_t *server = NULL;
|
||||
|
||||
OpenAPI_subscription_data_t *SubscriptionData = NULL;
|
||||
|
||||
ogs_assert(subscription);
|
||||
ogs_assert(subscription->nf_type);
|
||||
|
||||
memset(&message, 0, sizeof(message));
|
||||
message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST;
|
||||
message.h.service.name = (char *)OGS_SBI_SERVICE_NAME_NRF_NFM;
|
||||
message.h.api.version = (char *)OGS_SBI_API_VERSION;
|
||||
message.h.resource.name = (char *)OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS;
|
||||
|
||||
SubscriptionData = ogs_calloc(1, sizeof(*SubscriptionData));
|
||||
ogs_assert(SubscriptionData);
|
||||
|
||||
server = ogs_list_first(&ogs_sbi_self()->server_list);
|
||||
ogs_assert(server);
|
||||
|
||||
SubscriptionData->nf_status_notification_uri = ogs_sbi_server_uri(server,
|
||||
OGS_SBI_SERVICE_NAME_NRF_NFM, OGS_SBI_API_VERSION,
|
||||
OGS_SBI_RESOURCE_NAME_NF_STATUS_NOTIFY, NULL);
|
||||
ogs_assert(SubscriptionData->nf_status_notification_uri);
|
||||
|
||||
SubscriptionData->req_nf_type = subscription->nf_type;
|
||||
SubscriptionData->req_nf_instance_id = subscription->nf_instance_id;
|
||||
|
||||
message.SubscriptionData = SubscriptionData;
|
||||
|
||||
request = ogs_sbi_build_request(&message);
|
||||
ogs_assert(request);
|
||||
|
||||
ogs_free(SubscriptionData->nf_status_notification_uri);
|
||||
ogs_free(SubscriptionData);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
ogs_sbi_request_t *amf_nnrf_build_nf_status_unsubscribe(
|
||||
ogs_sbi_subscription_t *subscription)
|
||||
{
|
||||
ogs_sbi_message_t message;
|
||||
ogs_sbi_request_t *request = NULL;
|
||||
|
||||
ogs_assert(subscription);
|
||||
|
||||
memset(&message, 0, sizeof(message));
|
||||
message.h.method = (char *)OGS_SBI_HTTP_METHOD_DELETE;
|
||||
message.h.service.name = (char *)OGS_SBI_SERVICE_NAME_NRF_NFM;
|
||||
message.h.api.version = (char *)OGS_SBI_API_VERSION;
|
||||
message.h.resource.name = (char *)OGS_SBI_RESOURCE_NAME_SUBSCRIPTIONS;
|
||||
message.h.resource.id = subscription->id;
|
||||
|
||||
request = ogs_sbi_build_request(&message);
|
||||
ogs_assert(request);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
ogs_sbi_request_t *amf_nnrf_build_nf_discover(
|
||||
OpenAPI_nf_type_e target_nf_type, OpenAPI_nf_type_e requester_nf_type)
|
||||
{
|
||||
ogs_sbi_message_t message;
|
||||
ogs_sbi_request_t *request = NULL;
|
||||
|
||||
ogs_assert(target_nf_type);
|
||||
ogs_assert(requester_nf_type);
|
||||
|
||||
memset(&message, 0, sizeof(message));
|
||||
message.h.method = (char *)OGS_SBI_HTTP_METHOD_GET;
|
||||
message.h.service.name = (char *)OGS_SBI_SERVICE_NAME_NRF_DISC;
|
||||
message.h.api.version = (char *)OGS_SBI_API_VERSION;
|
||||
message.h.resource.name = (char *)OGS_SBI_RESOURCE_NAME_NF_INSTANCES;
|
||||
|
||||
message.param.target_nf_type = target_nf_type;
|
||||
message.param.requester_nf_type = requester_nf_type;
|
||||
|
||||
request = ogs_sbi_build_request(&message);
|
||||
ogs_assert(request);
|
||||
|
||||
return request;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef AMF_NNRF_BUILD_H
|
||||
#define AMF_NNRF_BUILD_H
|
||||
|
||||
#include "ogs-sbi.h"
|
||||
#include "context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
ogs_sbi_request_t *amf_nnrf_build_nf_register(
|
||||
ogs_sbi_nf_instance_t *nf_instance);
|
||||
ogs_sbi_request_t *amf_nnrf_build_nf_update(
|
||||
ogs_sbi_nf_instance_t *nf_instance);
|
||||
ogs_sbi_request_t *amf_nnrf_build_nf_de_register(
|
||||
ogs_sbi_nf_instance_t *nf_instance);
|
||||
|
||||
ogs_sbi_request_t *amf_nnrf_build_nf_status_subscribe(
|
||||
ogs_sbi_subscription_t *subscription);
|
||||
ogs_sbi_request_t *amf_nnrf_build_nf_status_unsubscribe(
|
||||
ogs_sbi_subscription_t *subscription);
|
||||
|
||||
ogs_sbi_request_t *amf_nnrf_build_nf_discover(
|
||||
OpenAPI_nf_type_e target_nf_type, OpenAPI_nf_type_e requester_nf_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AMF_NNRF_BUILD_H */
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "sbi-path.h"
|
||||
#include "nnrf-handler.h"
|
||||
|
||||
void amf_nnrf_handle_nf_register(
|
||||
ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_message_t *message)
|
||||
{
|
||||
OpenAPI_nf_profile_t *NFProfile = NULL;
|
||||
ogs_sbi_client_t *client = NULL;
|
||||
|
||||
ogs_assert(message);
|
||||
ogs_assert(nf_instance);
|
||||
client = nf_instance->client;
|
||||
ogs_assert(client);
|
||||
|
||||
NFProfile = message->NFProfile;
|
||||
if (!NFProfile) {
|
||||
ogs_error("No NFProfile");
|
||||
return;
|
||||
}
|
||||
|
||||
/* TIME : Update heartbeat from NRF */
|
||||
nf_instance->time.heartbeat = NFProfile->heart_beat_timer;
|
||||
}
|
||||
|
||||
void amf_nnrf_handle_nf_status_subscribe(
|
||||
ogs_sbi_subscription_t *subscription, ogs_sbi_message_t *message)
|
||||
{
|
||||
OpenAPI_subscription_data_t *SubscriptionData = NULL;
|
||||
ogs_sbi_client_t *client = NULL;
|
||||
|
||||
ogs_assert(message);
|
||||
ogs_assert(subscription);
|
||||
client = subscription->client;
|
||||
ogs_assert(client);
|
||||
|
||||
SubscriptionData = message->SubscriptionData;
|
||||
if (!SubscriptionData) {
|
||||
ogs_error("No SubscriptionData");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SubscriptionData->subscription_id) {
|
||||
ogs_error("No SubscriptionId");
|
||||
return;
|
||||
}
|
||||
ogs_sbi_subscription_set_id(
|
||||
subscription, SubscriptionData->subscription_id);
|
||||
|
||||
if (SubscriptionData->validity_time) {
|
||||
struct timeval tv;
|
||||
struct tm local, next;
|
||||
ogs_time_t diff, duration;
|
||||
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) {
|
||||
ogs_warn("Validation period [%d seconds, %s] is too small",
|
||||
(int)diff, SubscriptionData->validity_time);
|
||||
duration = VALIDITY_MINIMUM;
|
||||
ogs_warn("Forced to %d seconds", 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool amf_nnrf_handle_nf_status_notify(ogs_sbi_server_t *server,
|
||||
ogs_sbi_session_t *session, ogs_sbi_message_t *message)
|
||||
{
|
||||
ogs_sbi_response_t *response = NULL;
|
||||
OpenAPI_notification_data_t *NotificationData = NULL;
|
||||
OpenAPI_nf_profile_t *NFProfile = NULL;
|
||||
ogs_sbi_nf_instance_t *nf_instance = NULL;
|
||||
bool handled;
|
||||
|
||||
ogs_assert(session);
|
||||
ogs_assert(message);
|
||||
|
||||
NotificationData = message->NotificationData;
|
||||
if (!NotificationData) {
|
||||
ogs_error("No NotificationData");
|
||||
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
message, "No NotificationData", NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
NFProfile = NotificationData->nf_profile;
|
||||
if (!NFProfile) {
|
||||
ogs_error("No NFProfile");
|
||||
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
message, "No NFProfile", NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NFProfile->nf_instance_id) {
|
||||
ogs_error("No NFProfile.NFInstanceId");
|
||||
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
message, "No NFProfile", "NFInstanceId");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!NFProfile->nf_instance_id) {
|
||||
ogs_error("No NFProfile.NFInstanceId");
|
||||
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
message, "No NFProfile", "NFInstanceId");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NF_INSTANCE_IS_SELF(NFProfile->nf_instance_id)) {
|
||||
ogs_error("The notification is not allowed [%s]",
|
||||
NFProfile->nf_instance_id);
|
||||
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_FORBIDDEN,
|
||||
message, "The notification is not allowed",
|
||||
NFProfile->nf_instance_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NotificationData->event ==
|
||||
OpenAPI_notification_event_type_NF_REGISTERED) {
|
||||
ogs_sbi_client_t *client = NULL;
|
||||
|
||||
nf_instance = ogs_sbi_nf_instance_find(NFProfile->nf_instance_id);
|
||||
if (!nf_instance) {
|
||||
nf_instance = ogs_sbi_nf_instance_add(NFProfile->nf_instance_id);
|
||||
ogs_assert(nf_instance);
|
||||
|
||||
amf_nf_fsm_init(nf_instance);
|
||||
ogs_info("(NRF-notify) NF registered [%s]", nf_instance->id);
|
||||
} else
|
||||
ogs_warn("(NRF-notify) NF [%s] has already been added",
|
||||
NFProfile->nf_instance_id);
|
||||
|
||||
handled = ogs_sbi_nnrf_handle_nf_profile(
|
||||
nf_instance, NFProfile, session, message);
|
||||
if (!handled) return false;
|
||||
|
||||
ogs_info("(NRF-notify) NF Profile updated [%s]", nf_instance->id);
|
||||
|
||||
client = ogs_sbi_nf_instance_find_client(nf_instance);
|
||||
if (!client) {
|
||||
ogs_error("Cannot find client [%s]", nf_instance->id);
|
||||
ogs_sbi_server_send_error(session,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
message, "Cannot find client", nf_instance->id);
|
||||
return false;
|
||||
}
|
||||
amf_sbi_nf_associate_client(nf_instance, client);
|
||||
|
||||
} else if (NotificationData->event ==
|
||||
OpenAPI_notification_event_type_NF_DEREGISTERED) {
|
||||
nf_instance = ogs_sbi_nf_instance_find(NFProfile->nf_instance_id);
|
||||
if (nf_instance) {
|
||||
ogs_info("(NRF-notify) NF de-registered [%s]", nf_instance->id);
|
||||
amf_nf_fsm_fini(nf_instance);
|
||||
ogs_sbi_nf_instance_remove(nf_instance);
|
||||
|
||||
/* FIXME : Remove unnecessary Client */
|
||||
} else {
|
||||
ogs_warn("(NRF-notify) Not found [%s]", NFProfile->nf_instance_id);
|
||||
ogs_sbi_server_send_error(session,
|
||||
OGS_SBI_HTTP_STATUS_NOT_FOUND,
|
||||
message, "Not found", message->h.resource.id);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
char *eventstr = OpenAPI_notification_event_type_ToString(
|
||||
NotificationData->event);
|
||||
ogs_error("Not supported event [%d:%s]",
|
||||
NotificationData->event, eventstr ? eventstr : "Unknown");
|
||||
ogs_sbi_server_send_error(session, OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
message, "Not supported event",
|
||||
eventstr ? eventstr : "Unknown");
|
||||
return false;
|
||||
}
|
||||
|
||||
response = ogs_sbi_build_response(message);
|
||||
ogs_assert(response);
|
||||
ogs_sbi_server_send_response(session, response,
|
||||
OGS_SBI_HTTP_STATUS_NO_CONTENT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void amf_nnrf_handle_nf_discover(ogs_sbi_message_t *message)
|
||||
{
|
||||
OpenAPI_search_result_t *SearchResult = NULL;
|
||||
OpenAPI_lnode_t *node = NULL;
|
||||
bool handled;
|
||||
|
||||
ogs_assert(message);
|
||||
|
||||
SearchResult = message->SearchResult;
|
||||
if (!SearchResult) {
|
||||
ogs_error("No SearchResult");
|
||||
return;
|
||||
}
|
||||
|
||||
OpenAPI_list_for_each(SearchResult->nf_instances, node) {
|
||||
OpenAPI_nf_profile_t *NFProfile = NULL;
|
||||
ogs_sbi_nf_instance_t *nf_instance = NULL;
|
||||
ogs_sbi_client_t *client = NULL;
|
||||
|
||||
if (!node->data) continue;
|
||||
|
||||
NFProfile = node->data;
|
||||
|
||||
nf_instance = ogs_sbi_nf_instance_find(NFProfile->nf_instance_id);
|
||||
if (!nf_instance) {
|
||||
nf_instance = ogs_sbi_nf_instance_add(NFProfile->nf_instance_id);
|
||||
ogs_assert(nf_instance);
|
||||
|
||||
amf_nf_fsm_init(nf_instance);
|
||||
ogs_info("(NF-discover) NF registered [%s]", nf_instance->id);
|
||||
} else
|
||||
ogs_warn("(NF-discover) NF [%s] has already been added",
|
||||
NFProfile->nf_instance_id);
|
||||
|
||||
if (NF_INSTANCE_IS_OTHERS(nf_instance->id)) {
|
||||
handled = ogs_sbi_nnrf_handle_nf_profile(
|
||||
nf_instance, NFProfile, NULL, NULL);
|
||||
if (!handled) {
|
||||
ogs_error("ogs_sbi_nnrf_handle_nf_profile() failed [%s]",
|
||||
nf_instance->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
client = ogs_sbi_nf_instance_find_client(nf_instance);
|
||||
if (!client) {
|
||||
ogs_error("Cannot find client [%s]", nf_instance->id);
|
||||
continue;
|
||||
}
|
||||
amf_sbi_nf_associate_client(nf_instance, client);
|
||||
|
||||
/* TIME : Update validity from NRF */
|
||||
if (SearchResult->validity_period) {
|
||||
nf_instance->time.validity = SearchResult->validity_period;
|
||||
|
||||
ogs_assert(nf_instance->t_validity);
|
||||
ogs_timer_start(nf_instance->t_validity,
|
||||
ogs_time_from_sec(nf_instance->time.validity));
|
||||
|
||||
} else
|
||||
ogs_warn("NF Instance validity-time should not 0");
|
||||
|
||||
ogs_info("(NF-discover) NF Profile updated [%s]", nf_instance->id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef AMF_NNRF_HANDLER_H
|
||||
#define AMF_NNRF_HANDLER_H
|
||||
|
||||
#include "ogs-sbi.h"
|
||||
#include "context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void amf_nnrf_handle_nf_register(
|
||||
ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_message_t *message);
|
||||
void amf_nnrf_handle_nf_status_subscribe(
|
||||
ogs_sbi_subscription_t *subscription, ogs_sbi_message_t *message);
|
||||
|
||||
bool amf_nnrf_handle_nf_status_notify(ogs_sbi_server_t *server,
|
||||
ogs_sbi_session_t *session, ogs_sbi_message_t *message);
|
||||
|
||||
void amf_nnrf_handle_nf_discover(ogs_sbi_message_t *message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AMF_NNRF_HANDLER_H */
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "context.h"
|
||||
#include "sbi-path.h"
|
||||
|
||||
static int server_cb(ogs_sbi_server_t *server,
|
||||
ogs_sbi_session_t *session, ogs_sbi_request_t *request)
|
||||
{
|
||||
amf_event_t *e = NULL;
|
||||
int rv;
|
||||
|
||||
ogs_assert(session);
|
||||
ogs_assert(request);
|
||||
|
||||
e = amf_event_new(AMF_EVT_SBI_SERVER);
|
||||
ogs_assert(e);
|
||||
|
||||
e->sbi.server = server;
|
||||
e->sbi.session = session;
|
||||
e->sbi.request = request;
|
||||
|
||||
rv = ogs_queue_push(amf_self()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
|
||||
amf_event_free(e);
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
static int client_cb(ogs_sbi_response_t *response, void *data)
|
||||
{
|
||||
amf_event_t *e = NULL;
|
||||
int rv;
|
||||
|
||||
ogs_assert(response);
|
||||
|
||||
e = amf_event_new(AMF_EVT_SBI_CLIENT);
|
||||
ogs_assert(e);
|
||||
e->sbi.response = response;
|
||||
e->sbi.data = data;
|
||||
|
||||
rv = ogs_queue_push(amf_self()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_warn("ogs_queue_push() failed:%d", (int)rv);
|
||||
amf_event_free(e);
|
||||
return OGS_ERROR;
|
||||
}
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
int amf_sbi_open(void)
|
||||
{
|
||||
ogs_sbi_nf_instance_t *nf_instance = NULL;
|
||||
ogs_sbi_client_t *client = NULL;
|
||||
|
||||
ogs_sbi_server_start_all(server_cb);
|
||||
|
||||
ogs_list_for_each(&ogs_sbi_self()->client_list, client) {
|
||||
ogs_sbi_nf_service_t *service = NULL;
|
||||
|
||||
nf_instance = ogs_sbi_nf_instance_build_default(
|
||||
amf_self()->nf_type, client);
|
||||
ogs_assert(nf_instance);
|
||||
|
||||
service = ogs_sbi_nf_service_build_default(nf_instance,
|
||||
(char*)OGS_SBI_SERVICE_NAME_SMF_PDUSESSION, client);
|
||||
ogs_assert(service);
|
||||
ogs_sbi_nf_service_add_version(service, (char*)OGS_SBI_API_VERSION,
|
||||
(char*)OGS_SBI_API_FULL_VERSION, NULL);
|
||||
|
||||
amf_sbi_nf_associate_client(nf_instance, client);
|
||||
amf_nf_fsm_init(nf_instance);
|
||||
}
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
void amf_sbi_close(void)
|
||||
{
|
||||
ogs_sbi_server_stop_all();
|
||||
}
|
||||
|
||||
void amf_sbi_nf_associate_client(
|
||||
ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_client_t *client)
|
||||
{
|
||||
ogs_assert(nf_instance);
|
||||
ogs_assert(client);
|
||||
|
||||
OGS_SETUP_SBI_CLIENT(nf_instance, client);
|
||||
client->cb = client_cb;
|
||||
}
|
||||
|
||||
void amf_sbi_send_nf_register(ogs_sbi_nf_instance_t *nf_instance)
|
||||
{
|
||||
ogs_sbi_request_t *request = NULL;
|
||||
ogs_sbi_client_t *client = NULL;
|
||||
|
||||
ogs_assert(nf_instance);
|
||||
client = nf_instance->client;
|
||||
ogs_assert(client);
|
||||
|
||||
request = amf_nnrf_build_nf_register(nf_instance);
|
||||
ogs_assert(request);
|
||||
ogs_sbi_client_send_request(client, request, nf_instance);
|
||||
}
|
||||
|
||||
void amf_sbi_send_nf_update(ogs_sbi_nf_instance_t *nf_instance)
|
||||
{
|
||||
ogs_sbi_request_t *request = NULL;
|
||||
ogs_sbi_client_t *client = NULL;
|
||||
|
||||
ogs_assert(nf_instance);
|
||||
client = nf_instance->client;
|
||||
ogs_assert(client);
|
||||
|
||||
request = amf_nnrf_build_nf_update(nf_instance);
|
||||
ogs_assert(request);
|
||||
ogs_sbi_client_send_request(client, request, nf_instance);
|
||||
}
|
||||
|
||||
void amf_sbi_send_nf_de_register(ogs_sbi_nf_instance_t *nf_instance)
|
||||
{
|
||||
ogs_sbi_request_t *request = NULL;
|
||||
ogs_sbi_client_t *client = NULL;
|
||||
|
||||
ogs_assert(nf_instance);
|
||||
client = nf_instance->client;
|
||||
ogs_assert(client);
|
||||
|
||||
request = amf_nnrf_build_nf_de_register(nf_instance);
|
||||
ogs_assert(request);
|
||||
ogs_sbi_client_send_request(client, request, nf_instance);
|
||||
}
|
||||
|
||||
void amf_sbi_send_nf_status_subscribe(ogs_sbi_client_t *client,
|
||||
OpenAPI_nf_type_e nf_type, char *nf_instance_id)
|
||||
{
|
||||
ogs_sbi_request_t *request = NULL;
|
||||
ogs_sbi_subscription_t *subscription = NULL;
|
||||
|
||||
ogs_assert(client);
|
||||
|
||||
subscription = ogs_sbi_subscription_add();
|
||||
ogs_assert(subscription);
|
||||
subscription->client = client;
|
||||
subscription->nf_type = nf_type;
|
||||
if (nf_instance_id)
|
||||
subscription->nf_instance_id = ogs_strdup(nf_instance_id);
|
||||
|
||||
request = amf_nnrf_build_nf_status_subscribe(subscription);
|
||||
ogs_assert(request);
|
||||
ogs_sbi_client_send_request(client, request, subscription);
|
||||
}
|
||||
|
||||
void amf_sbi_send_nf_status_unsubscribe(ogs_sbi_subscription_t *subscription)
|
||||
{
|
||||
ogs_sbi_request_t *request = NULL;
|
||||
ogs_sbi_client_t *client = NULL;
|
||||
|
||||
ogs_assert(subscription);
|
||||
client = subscription->client;
|
||||
ogs_assert(client);
|
||||
|
||||
request = amf_nnrf_build_nf_status_unsubscribe(subscription);
|
||||
ogs_assert(request);
|
||||
ogs_sbi_client_send_request(client, request, subscription);
|
||||
}
|
||||
|
||||
void amf_sbi_send_nf_discover(ogs_sbi_client_t *client,
|
||||
OpenAPI_nf_type_e target_nf_type, OpenAPI_nf_type_e requester_nf_type)
|
||||
{
|
||||
ogs_sbi_request_t *request = NULL;
|
||||
|
||||
ogs_assert(client);
|
||||
|
||||
request = amf_nnrf_build_nf_discover(target_nf_type, requester_nf_type);
|
||||
ogs_assert(request);
|
||||
ogs_sbi_client_send_request(client, request, NULL);
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef AMF_SBI_PATH_H
|
||||
#define AMF_SBI_PATH_H
|
||||
|
||||
#include "nnrf-build.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int amf_sbi_open(void);
|
||||
void amf_sbi_close(void);
|
||||
|
||||
void amf_sbi_nf_associate_client(
|
||||
ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_client_t *client);
|
||||
|
||||
void amf_sbi_send_nf_register(ogs_sbi_nf_instance_t *nf_instance);
|
||||
void amf_sbi_send_nf_update(ogs_sbi_nf_instance_t *nf_instance);
|
||||
void amf_sbi_send_nf_de_register(ogs_sbi_nf_instance_t *nf_instance);
|
||||
|
||||
void amf_sbi_send_nf_status_subscribe(ogs_sbi_client_t *client,
|
||||
OpenAPI_nf_type_e nf_type, char *nf_instance_id);
|
||||
void amf_sbi_send_nf_status_unsubscribe(ogs_sbi_subscription_t *subscription);
|
||||
|
||||
void amf_sbi_send_nf_discover(ogs_sbi_client_t *client,
|
||||
OpenAPI_nf_type_e target_nf_type, OpenAPI_nf_type_e requester_nf_type);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AMF_SBI_PATH_H */
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "context.h"
|
||||
|
||||
static amf_timer_cfg_t g_amf_timer_cfg[MAX_NUM_OF_AMF_TIMER] = {
|
||||
[AMF_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL] =
|
||||
{ .duration = ogs_time_from_sec(3) },
|
||||
};
|
||||
|
||||
amf_timer_cfg_t *amf_timer_cfg(amf_timer_e id)
|
||||
{
|
||||
ogs_assert(id < MAX_NUM_OF_AMF_TIMER);
|
||||
return &g_amf_timer_cfg[id];
|
||||
}
|
||||
|
||||
const char *amf_timer_get_name(amf_timer_e id)
|
||||
{
|
||||
switch (id) {
|
||||
case AMF_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL:
|
||||
return "AMF_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL";
|
||||
case AMF_TIMER_NF_INSTANCE_HEARTBEAT_INTERVAL:
|
||||
return "AMF_TIMER_NF_INSTANCE_HEARTBEAT_INTERVAL";
|
||||
case AMF_TIMER_NF_INSTANCE_HEARTBEAT:
|
||||
return "AMF_TIMER_NF_INSTANCE_HEARTBEAT";
|
||||
case AMF_TIMER_NF_INSTANCE_VALIDITY:
|
||||
return "AMF_TIMER_NF_INSTANCE_VALIDITY";
|
||||
case AMF_TIMER_SUBSCRIPTION_VALIDITY:
|
||||
return "AMF_TIMER_SUBSCRIPTION_VALIDITY";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "UNKNOWN_TIMER";
|
||||
}
|
||||
|
||||
static void timer_send_event(int timer_id, void *data)
|
||||
{
|
||||
int rv;
|
||||
amf_event_t *e = NULL;
|
||||
ogs_assert(data);
|
||||
|
||||
switch (timer_id) {
|
||||
case AMF_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL:
|
||||
case AMF_TIMER_NF_INSTANCE_HEARTBEAT_INTERVAL:
|
||||
case AMF_TIMER_NF_INSTANCE_HEARTBEAT:
|
||||
case AMF_TIMER_NF_INSTANCE_VALIDITY:
|
||||
case AMF_TIMER_SUBSCRIPTION_VALIDITY:
|
||||
e = amf_event_new(AMF_EVT_SBI_TIMER);
|
||||
ogs_assert(e);
|
||||
e->timer_id = timer_id;
|
||||
e->sbi.data = data;
|
||||
break;
|
||||
default:
|
||||
ogs_fatal("Unknown timer id[%d]", timer_id);
|
||||
ogs_assert_if_reached();
|
||||
break;
|
||||
}
|
||||
|
||||
rv = ogs_queue_push(amf_self()->queue, e);
|
||||
if (rv != OGS_OK) {
|
||||
ogs_warn("ogs_queue_push() failed [%d] in %s",
|
||||
(int)rv, amf_timer_get_name(e->timer_id));
|
||||
amf_event_free(e);
|
||||
}
|
||||
}
|
||||
|
||||
void amf_timer_nf_instance_registration_interval(void *data)
|
||||
{
|
||||
timer_send_event(AMF_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL, data);
|
||||
}
|
||||
|
||||
void amf_timer_nf_instance_heartbeat_interval(void *data)
|
||||
{
|
||||
timer_send_event(AMF_TIMER_NF_INSTANCE_HEARTBEAT_INTERVAL, data);
|
||||
}
|
||||
|
||||
void amf_timer_nf_instance_heartbeat(void *data)
|
||||
{
|
||||
timer_send_event(AMF_TIMER_NF_INSTANCE_HEARTBEAT, data);
|
||||
}
|
||||
|
||||
void amf_timer_nf_instance_validity(void *data)
|
||||
{
|
||||
timer_send_event(AMF_TIMER_NF_INSTANCE_VALIDITY, data);
|
||||
}
|
||||
|
||||
void amf_timer_subscription_validity(void *data)
|
||||
{
|
||||
timer_send_event(AMF_TIMER_SUBSCRIPTION_VALIDITY, data);
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef AMF_TIMER_H
|
||||
#define AMF_TIMER_H
|
||||
|
||||
#include "ogs-core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* forward declaration */
|
||||
typedef enum {
|
||||
AMF_TIMER_BASE = 0,
|
||||
|
||||
AMF_TIMER_NF_INSTANCE_REGISTRATION_INTERVAL,
|
||||
AMF_TIMER_NF_INSTANCE_HEARTBEAT_INTERVAL,
|
||||
AMF_TIMER_NF_INSTANCE_HEARTBEAT,
|
||||
AMF_TIMER_NF_INSTANCE_VALIDITY,
|
||||
AMF_TIMER_SUBSCRIPTION_VALIDITY,
|
||||
|
||||
MAX_NUM_OF_AMF_TIMER,
|
||||
|
||||
} amf_timer_e;
|
||||
|
||||
typedef struct amf_timer_cfg_s {
|
||||
int max_count;
|
||||
ogs_time_t duration;
|
||||
} amf_timer_cfg_t;
|
||||
|
||||
amf_timer_cfg_t *amf_timer_cfg(amf_timer_e id);
|
||||
|
||||
const char *amf_timer_get_name(amf_timer_e id);
|
||||
|
||||
void amf_timer_nf_instance_registration_interval(void *data);
|
||||
void amf_timer_nf_instance_heartbeat_interval(void *data);
|
||||
void amf_timer_nf_instance_heartbeat(void *data);
|
||||
void amf_timer_nf_instance_validity(void *data);
|
||||
void amf_timer_subscription_validity(void *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* AMF_TIMER_H */
|
|
@ -28,5 +28,6 @@ subdir('pgw')
|
|||
subdir('pcrf')
|
||||
|
||||
subdir('nrf')
|
||||
subdir('smf')
|
||||
subdir('upf')
|
||||
subdir('smf')
|
||||
subdir('amf')
|
||||
|
|
|
@ -70,7 +70,7 @@ ogs_pkbuf_t *emm_build_attach_accept(
|
|||
served_tai_index = mme_find_served_tai(&mme_ue->tai);
|
||||
ogs_debug(" SERVED_TAI_INDEX[%d]", served_tai_index);
|
||||
ogs_assert(served_tai_index >= 0 &&
|
||||
served_tai_index < MAX_NUM_OF_SERVED_TAI);
|
||||
served_tai_index < OGS_MAX_NUM_OF_SERVED_TAI);
|
||||
ogs_nas_tai_list_build(&attach_accept->tai_list,
|
||||
&mme_self()->served_tai[served_tai_index].list0,
|
||||
&mme_self()->served_tai[served_tai_index].list2);
|
||||
|
@ -368,7 +368,7 @@ ogs_pkbuf_t *emm_build_tau_accept(mme_ue_t *mme_ue)
|
|||
served_tai_index = mme_find_served_tai(&mme_ue->tai);
|
||||
ogs_debug(" SERVED_TAI_INDEX[%d]", served_tai_index);
|
||||
ogs_assert(served_tai_index >= 0 &&
|
||||
served_tai_index < MAX_NUM_OF_SERVED_TAI);
|
||||
served_tai_index < OGS_MAX_NUM_OF_SERVED_TAI);
|
||||
ogs_nas_tai_list_build(&tau_accept->tai_list,
|
||||
&mme_self()->served_tai[served_tai_index].list0,
|
||||
&mme_self()->served_tai[served_tai_index].list2);
|
||||
|
|
|
@ -39,7 +39,7 @@ int emm_handle_attach_request(
|
|||
int served_tai_index = 0;
|
||||
|
||||
ogs_nas_eps_mobile_identity_guti_t *eps_mobile_identity_guti = NULL;
|
||||
ogs_nas_guti_t nas_guti;
|
||||
ogs_nas_eps_guti_t nas_guti;
|
||||
|
||||
enb_ue_t *enb_ue = NULL;
|
||||
ogs_nas_eps_attach_type_t *eps_attach_type =
|
||||
|
@ -101,7 +101,7 @@ int emm_handle_attach_request(
|
|||
enb_ue->saved.e_cgi.cell_id);
|
||||
|
||||
/* Copy TAI and ECGI from enb_ue */
|
||||
memcpy(&mme_ue->tai, &enb_ue->saved.tai, sizeof(ogs_tai_t));
|
||||
memcpy(&mme_ue->tai, &enb_ue->saved.tai, sizeof(ogs_eps_tai_t));
|
||||
memcpy(&mme_ue->e_cgi, &enb_ue->saved.e_cgi, sizeof(ogs_e_cgi_t));
|
||||
|
||||
/* Check TAI */
|
||||
|
@ -120,7 +120,7 @@ int emm_handle_attach_request(
|
|||
/* Store UE specific information */
|
||||
if (attach_request->presencemask &
|
||||
OGS_NAS_EPS_ATTACH_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT) {
|
||||
ogs_nas_tracking_area_identity_t *last_visited_registered_tai =
|
||||
ogs_nas_eps_tai_t *last_visited_registered_tai =
|
||||
&attach_request->last_visited_registered_tai;
|
||||
|
||||
ogs_nas_to_plmn_id(&mme_ue->last_visited_plmn_id,
|
||||
|
@ -426,7 +426,7 @@ int emm_handle_tau_request(mme_ue_t *mme_ue,
|
|||
int served_tai_index = 0;
|
||||
|
||||
ogs_nas_eps_mobile_identity_guti_t *eps_mobile_identity_guti = NULL;
|
||||
ogs_nas_guti_t nas_guti;
|
||||
ogs_nas_eps_guti_t nas_guti;
|
||||
|
||||
ogs_nas_eps_update_type_t *eps_update_type =
|
||||
&tau_request->eps_update_type;
|
||||
|
@ -486,7 +486,7 @@ int emm_handle_tau_request(mme_ue_t *mme_ue,
|
|||
enb_ue->saved.e_cgi.cell_id);
|
||||
|
||||
/* Copy TAI and ECGI from enb_ue */
|
||||
memcpy(&mme_ue->tai, &enb_ue->saved.tai, sizeof(ogs_tai_t));
|
||||
memcpy(&mme_ue->tai, &enb_ue->saved.tai, sizeof(ogs_eps_tai_t));
|
||||
memcpy(&mme_ue->e_cgi, &enb_ue->saved.e_cgi, sizeof(ogs_e_cgi_t));
|
||||
|
||||
/* Check TAI */
|
||||
|
@ -503,7 +503,7 @@ int emm_handle_tau_request(mme_ue_t *mme_ue,
|
|||
/* Store UE specific information */
|
||||
if (tau_request->presencemask &
|
||||
OGS_NAS_EPS_TRACKING_AREA_UPDATE_REQUEST_LAST_VISITED_REGISTERED_TAI_PRESENT) {
|
||||
ogs_nas_tracking_area_identity_t *last_visited_registered_tai =
|
||||
ogs_nas_eps_tai_t *last_visited_registered_tai =
|
||||
&tau_request->last_visited_registered_tai;
|
||||
|
||||
ogs_nas_to_plmn_id(&mme_ue->last_visited_plmn_id,
|
||||
|
@ -609,7 +609,7 @@ int emm_handle_extended_service_request(mme_ue_t *mme_ue,
|
|||
enb_ue->saved.e_cgi.cell_id);
|
||||
|
||||
/* Copy TAI and ECGI from enb_ue */
|
||||
memcpy(&mme_ue->tai, &enb_ue->saved.tai, sizeof(ogs_tai_t));
|
||||
memcpy(&mme_ue->tai, &enb_ue->saved.tai, sizeof(ogs_eps_tai_t));
|
||||
memcpy(&mme_ue->e_cgi, &enb_ue->saved.e_cgi, sizeof(ogs_e_cgi_t));
|
||||
|
||||
/* Check TAI */
|
||||
|
|
|
@ -125,7 +125,7 @@ void mme_context_init()
|
|||
ogs_pool_init(&mme_csmap_pool, ogs_config()->max.csmap);
|
||||
|
||||
/* Allocate TWICE the pool to check if maximum number of eNBs is reached */
|
||||
ogs_pool_init(&mme_enb_pool, ogs_config()->max.enb*2);
|
||||
ogs_pool_init(&mme_enb_pool, ogs_config()->max.gnb*2);
|
||||
|
||||
ogs_pool_init(&mme_ue_pool, ogs_config()->pool.ue);
|
||||
ogs_pool_init(&enb_ue_pool, ogs_config()->pool.ue);
|
||||
|
@ -704,7 +704,7 @@ int mme_context_parse_config()
|
|||
ogs_plmn_id_t *plmn_id = NULL;
|
||||
const char *mcc = NULL, *mnc = NULL;
|
||||
ogs_assert(gummei->num_of_plmn_id <=
|
||||
MAX_PLMN_ID);
|
||||
OGS_MAX_NUM_OF_PLMN);
|
||||
plmn_id = &gummei->plmn_id[
|
||||
gummei->num_of_plmn_id];
|
||||
ogs_assert(plmn_id);
|
||||
|
@ -833,11 +833,11 @@ int mme_context_parse_config()
|
|||
YAML_SEQUENCE_NODE);
|
||||
} else if (!strcmp(mme_key, "tai")) {
|
||||
int num_of_list0 = 0;
|
||||
tai0_list_t *list0 = NULL;
|
||||
tai2_list_t *list2 = NULL;
|
||||
ogs_eps_tai0_list_t *list0 = NULL;
|
||||
ogs_eps_tai2_list_t *list2 = NULL;
|
||||
|
||||
ogs_assert(self.num_of_served_tai <=
|
||||
MAX_NUM_OF_SERVED_TAI);
|
||||
OGS_MAX_NUM_OF_SERVED_TAI);
|
||||
list0 = &self.served_tai[self.num_of_served_tai].list0;
|
||||
ogs_assert(list0);
|
||||
list2 = &self.served_tai[self.num_of_served_tai].list2;
|
||||
|
@ -923,9 +923,9 @@ int mme_context_parse_config()
|
|||
|
||||
list2->num++;
|
||||
if (list2->num > 1)
|
||||
list2->type = TAI2_TYPE;
|
||||
list2->type = OGS_TAI2_TYPE;
|
||||
else
|
||||
list2->type = TAI1_TYPE;
|
||||
list2->type = OGS_TAI1_TYPE;
|
||||
} else if (num_of_tac > 1) {
|
||||
int i;
|
||||
ogs_plmn_id_build(
|
||||
|
@ -936,7 +936,7 @@ int mme_context_parse_config()
|
|||
}
|
||||
|
||||
list0->tai[num_of_list0].num = num_of_tac;
|
||||
list0->tai[num_of_list0].type = TAI0_TYPE;
|
||||
list0->tai[num_of_list0].type = OGS_TAI0_TYPE;
|
||||
|
||||
num_of_list0++;
|
||||
}
|
||||
|
@ -1839,16 +1839,16 @@ void mme_csmap_remove_all(void)
|
|||
mme_csmap_remove(csmap);
|
||||
}
|
||||
|
||||
mme_csmap_t *mme_csmap_find_by_tai(ogs_tai_t *tai)
|
||||
mme_csmap_t *mme_csmap_find_by_tai(ogs_eps_tai_t *tai)
|
||||
{
|
||||
mme_csmap_t *csmap = NULL;
|
||||
ogs_assert(tai);
|
||||
|
||||
ogs_list_for_each(&self.csmap_list, csmap) {
|
||||
ogs_nas_tai_t ogs_nas_tai;
|
||||
ogs_nas_eps_tai_t ogs_nas_tai;
|
||||
ogs_nas_from_plmn_id(&ogs_nas_tai.nas_plmn_id, &tai->plmn_id);
|
||||
ogs_nas_tai.tac = tai->tac;
|
||||
if (memcmp(&csmap->tai, &ogs_nas_tai, sizeof(ogs_nas_tai_t)) == 0)
|
||||
if (memcmp(&csmap->tai, &ogs_nas_tai, sizeof(ogs_nas_eps_tai_t)) == 0)
|
||||
return csmap;
|
||||
}
|
||||
|
||||
|
@ -2134,11 +2134,11 @@ static int mme_ue_new_guti(mme_ue_t *mme_ue)
|
|||
/* MME has a VALID GUTI
|
||||
* As such, we need to remove previous GUTI in hash table */
|
||||
ogs_hash_set(self.guti_ue_hash,
|
||||
&mme_ue->guti, sizeof(ogs_nas_guti_t), NULL);
|
||||
&mme_ue->guti, sizeof(ogs_nas_eps_guti_t), NULL);
|
||||
ogs_assert(mme_m_tmsi_free(mme_ue->m_tmsi) == OGS_OK);
|
||||
}
|
||||
|
||||
memset(&mme_ue->guti, 0, sizeof(ogs_nas_guti_t));
|
||||
memset(&mme_ue->guti, 0, sizeof(ogs_nas_eps_guti_t));
|
||||
|
||||
/* Use the first configured plmn_id and mme group id */
|
||||
ogs_nas_from_plmn_id(&mme_ue->guti.nas_plmn_id, &served_gummei->plmn_id[0]);
|
||||
|
@ -2149,7 +2149,7 @@ static int mme_ue_new_guti(mme_ue_t *mme_ue)
|
|||
ogs_assert(mme_ue->m_tmsi);
|
||||
mme_ue->guti.m_tmsi = *(mme_ue->m_tmsi);
|
||||
ogs_hash_set(self.guti_ue_hash,
|
||||
&mme_ue->guti, sizeof(ogs_nas_guti_t), mme_ue);
|
||||
&mme_ue->guti, sizeof(ogs_nas_eps_guti_t), mme_ue);
|
||||
|
||||
return OGS_OK;
|
||||
}
|
||||
|
@ -2258,7 +2258,7 @@ void mme_ue_remove(mme_ue_t *mme_ue)
|
|||
/* Clear hash table */
|
||||
if (mme_ue->m_tmsi) {
|
||||
ogs_hash_set(self.guti_ue_hash,
|
||||
&mme_ue->guti, sizeof(ogs_nas_guti_t), NULL);
|
||||
&mme_ue->guti, sizeof(ogs_nas_eps_guti_t), NULL);
|
||||
ogs_assert(mme_m_tmsi_free(mme_ue->m_tmsi) == OGS_OK);
|
||||
}
|
||||
if (mme_ue->imsi_len != 0)
|
||||
|
@ -2271,10 +2271,10 @@ void mme_ue_remove(mme_ue_t *mme_ue)
|
|||
CLEAR_SERVICE_INDICATOR(mme_ue);
|
||||
|
||||
/* Free UeRadioCapability */
|
||||
OGS_S1AP_CLEAR_DATA(&mme_ue->ueRadioCapability);
|
||||
OGS_ASN_CLEAR_DATA(&mme_ue->ueRadioCapability);
|
||||
|
||||
/* Clear Transparent Container */
|
||||
OGS_S1AP_CLEAR_DATA(&mme_ue->container);
|
||||
OGS_ASN_CLEAR_DATA(&mme_ue->container);
|
||||
|
||||
/* Delete All Timers */
|
||||
CLEAR_MME_UE_ALL_TIMERS(mme_ue);
|
||||
|
@ -2319,12 +2319,12 @@ mme_ue_t *mme_ue_find_by_imsi(uint8_t *imsi, int imsi_len)
|
|||
return (mme_ue_t *)ogs_hash_get(self.imsi_ue_hash, imsi, imsi_len);
|
||||
}
|
||||
|
||||
mme_ue_t *mme_ue_find_by_guti(ogs_nas_guti_t *guti)
|
||||
mme_ue_t *mme_ue_find_by_guti(ogs_nas_eps_guti_t *guti)
|
||||
{
|
||||
ogs_assert(guti);
|
||||
|
||||
return (mme_ue_t *)ogs_hash_get(
|
||||
self.guti_ue_hash, guti, sizeof(ogs_nas_guti_t));
|
||||
self.guti_ue_hash, guti, sizeof(ogs_nas_eps_guti_t));
|
||||
}
|
||||
|
||||
mme_ue_t *mme_ue_find_by_teid(uint32_t teid)
|
||||
|
@ -2345,7 +2345,7 @@ mme_ue_t *mme_ue_find_by_message(ogs_nas_eps_message_t *message)
|
|||
ogs_nas_eps_mobile_identity_guti_t *eps_mobile_identity_guti = NULL;
|
||||
ogs_nas_mobile_identity_tmsi_t *mobile_identity_tmsi = NULL;
|
||||
served_gummei_t *served_gummei = NULL;
|
||||
ogs_nas_guti_t ogs_nas_guti;
|
||||
ogs_nas_eps_guti_t ogs_nas_guti;
|
||||
|
||||
switch (message->emm.h.message_type) {
|
||||
case OGS_NAS_EPS_ATTACH_REQUEST:
|
||||
|
@ -3079,20 +3079,20 @@ ogs_pdn_t *mme_default_pdn(mme_ue_t *mme_ue)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int mme_find_served_tai(ogs_tai_t *tai)
|
||||
int mme_find_served_tai(ogs_eps_tai_t *tai)
|
||||
{
|
||||
int i = 0, j = 0, k = 0;
|
||||
|
||||
ogs_assert(tai);
|
||||
|
||||
for (i = 0; i < self.num_of_served_tai; i++) {
|
||||
tai0_list_t *list0 = &self.served_tai[i].list0;
|
||||
ogs_eps_tai0_list_t *list0 = &self.served_tai[i].list0;
|
||||
ogs_assert(list0);
|
||||
tai2_list_t *list2 = &self.served_tai[i].list2;
|
||||
ogs_eps_tai2_list_t *list2 = &self.served_tai[i].list2;
|
||||
ogs_assert(list2);
|
||||
|
||||
for (j = 0; list0->tai[j].num; j++) {
|
||||
ogs_assert(list0->tai[j].type == TAI0_TYPE);
|
||||
ogs_assert(list0->tai[j].type == OGS_TAI0_TYPE);
|
||||
ogs_assert(list0->tai[j].num < OGS_MAX_NUM_OF_TAI);
|
||||
|
||||
for (k = 0; k < list0->tai[j].num; k++) {
|
||||
|
@ -3105,7 +3105,8 @@ int mme_find_served_tai(ogs_tai_t *tai)
|
|||
}
|
||||
|
||||
if (list2->num) {
|
||||
ogs_assert(list2->type == TAI1_TYPE || list2->type == TAI2_TYPE);
|
||||
ogs_assert(list2->type == OGS_TAI1_TYPE ||
|
||||
list2->type == OGS_TAI2_TYPE);
|
||||
ogs_assert(list2->num < OGS_MAX_NUM_OF_TAI);
|
||||
|
||||
for (j = 0; j < list2->num; j++) {
|
||||
|
@ -3208,17 +3209,3 @@ uint8_t mme_selected_enc_algorithm(mme_ue_t *mme_ue)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool mme_is_maximum_number_of_enbs_reached(void)
|
||||
{
|
||||
mme_enb_t *enb = NULL, *next_enb = NULL;
|
||||
int number_of_enbs_online = 0;
|
||||
|
||||
ogs_list_for_each_safe(&self.enb_list, next_enb, enb) {
|
||||
if (enb->state.s1_setup_success) {
|
||||
number_of_enbs_online++;
|
||||
}
|
||||
}
|
||||
|
||||
return number_of_enbs_online >= ogs_config()->max.enb;
|
||||
}
|
||||
|
|
|
@ -35,15 +35,10 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_PLMN_ID 6
|
||||
#define GRP_PER_MME 256 /* According to spec it is 65535 */
|
||||
#define CODE_PER_MME 256 /* According to spec it is 256 */
|
||||
|
||||
#define MAX_NUM_OF_SERVED_TAI 16
|
||||
#define MAX_NUM_OF_SERVED_GUMMEI 8
|
||||
#define MAX_NUM_OF_ALGORITHM 8
|
||||
|
||||
#define MAX_NUM_OF_BPLMN 6
|
||||
|
||||
extern int __mme_log_domain;
|
||||
extern int __emm_log_domain;
|
||||
|
@ -72,7 +67,7 @@ typedef enum {
|
|||
|
||||
typedef struct served_gummei_s {
|
||||
uint32_t num_of_plmn_id;
|
||||
ogs_plmn_id_t plmn_id[MAX_PLMN_ID];
|
||||
ogs_plmn_id_t plmn_id[OGS_MAX_NUM_OF_PLMN];
|
||||
|
||||
uint32_t num_of_mme_gid;
|
||||
uint16_t mme_gid[GRP_PER_MME];
|
||||
|
@ -117,9 +112,9 @@ typedef struct mme_context_s {
|
|||
/* Served TAI */
|
||||
uint8_t num_of_served_tai;
|
||||
struct {
|
||||
tai0_list_t list0;
|
||||
tai2_list_t list2;
|
||||
} served_tai[MAX_NUM_OF_SERVED_TAI];
|
||||
ogs_eps_tai0_list_t list0;
|
||||
ogs_eps_tai2_list_t list2;
|
||||
} served_tai[OGS_MAX_NUM_OF_SERVED_TAI];
|
||||
|
||||
/* defined in 'nas_ies.h'
|
||||
* #define NAS_SECURITY_ALGORITHMS_EIA0 0
|
||||
|
@ -127,14 +122,14 @@ typedef struct mme_context_s {
|
|||
* #define NAS_SECURITY_ALGORITHMS_128_EEA2 2
|
||||
* #define NAS_SECURITY_ALGORITHMS_128_EEA3 3 */
|
||||
uint8_t num_of_ciphering_order;
|
||||
uint8_t ciphering_order[MAX_NUM_OF_ALGORITHM];
|
||||
uint8_t ciphering_order[OGS_MAX_NUM_OF_ALGORITHM];
|
||||
/* defined in 'nas_ies.h'
|
||||
* #define NAS_SECURITY_ALGORITHMS_EIA0 0
|
||||
* #define NAS_SECURITY_ALGORITHMS_128_EIA1 1
|
||||
* #define NAS_SECURITY_ALGORITHMS_128_EIA1 2
|
||||
* #define NAS_SECURITY_ALGORITHMS_128_EIA3 3 */
|
||||
uint8_t num_of_integrity_order;
|
||||
uint8_t integrity_order[MAX_NUM_OF_ALGORITHM];
|
||||
uint8_t integrity_order[OGS_MAX_NUM_OF_ALGORITHM];
|
||||
|
||||
/* S1SetupResponse */
|
||||
uint8_t relative_capacity;
|
||||
|
@ -209,7 +204,7 @@ typedef struct mme_vlr_s {
|
|||
typedef struct mme_csmap_s {
|
||||
ogs_lnode_t lnode;
|
||||
|
||||
ogs_nas_tai_t tai;
|
||||
ogs_nas_eps_tai_t tai;
|
||||
ogs_nas_lai_t lai;
|
||||
|
||||
mme_vlr_t *vlr;
|
||||
|
@ -235,7 +230,7 @@ typedef struct mme_enb_s {
|
|||
|
||||
|
||||
uint8_t num_of_supported_ta_list;
|
||||
ogs_tai_t supported_ta_list[OGS_MAX_NUM_OF_TAI * MAX_NUM_OF_BPLMN];
|
||||
ogs_eps_tai_t supported_ta_list[OGS_MAX_NUM_OF_TAI*OGS_MAX_NUM_OF_BPLMN];
|
||||
|
||||
ogs_list_t enb_ue_list;
|
||||
|
||||
|
@ -261,7 +256,7 @@ struct enb_ue_s {
|
|||
*
|
||||
* Save TAI and ECGI. And then, this will copy 'mme_ue_t' context later */
|
||||
struct {
|
||||
ogs_tai_t tai;
|
||||
ogs_eps_tai_t tai;
|
||||
ogs_e_cgi_t e_cgi;
|
||||
} saved;
|
||||
|
||||
|
@ -317,7 +312,7 @@ struct mme_ue_s {
|
|||
|
||||
mme_m_tmsi_t *m_tmsi;
|
||||
mme_p_tmsi_t p_tmsi;
|
||||
ogs_nas_guti_t guti;
|
||||
ogs_nas_eps_guti_t guti;
|
||||
int guti_present;
|
||||
|
||||
uint32_t mme_s11_teid; /* MME-S11-TEID is derived from INDEX */
|
||||
|
@ -326,7 +321,7 @@ struct mme_ue_s {
|
|||
uint16_t vlr_ostream_id; /* SCTP output stream id for VLR */
|
||||
|
||||
/* UE Info */
|
||||
ogs_tai_t tai;
|
||||
ogs_eps_tai_t tai;
|
||||
ogs_e_cgi_t e_cgi;
|
||||
ogs_plmn_id_t last_visited_plmn_id;
|
||||
|
||||
|
@ -659,7 +654,7 @@ mme_csmap_t *mme_csmap_add(mme_vlr_t *vlr);
|
|||
void mme_csmap_remove(mme_csmap_t *csmap);
|
||||
void mme_csmap_remove_all(void);
|
||||
|
||||
mme_csmap_t *mme_csmap_find_by_tai(ogs_tai_t *tai);
|
||||
mme_csmap_t *mme_csmap_find_by_tai(ogs_eps_tai_t *tai);
|
||||
mme_csmap_t *mme_csmap_find_by_nas_lai(ogs_nas_lai_t *lai);
|
||||
|
||||
mme_enb_t *mme_enb_add(ogs_sock_t *sock, ogs_sockaddr_t *addr);
|
||||
|
@ -669,7 +664,6 @@ mme_enb_t *mme_enb_find_by_addr(ogs_sockaddr_t *addr);
|
|||
mme_enb_t *mme_enb_find_by_enb_id(uint32_t enb_id);
|
||||
int mme_enb_set_enb_id(mme_enb_t *enb, uint32_t enb_id);
|
||||
int mme_enb_sock_type(ogs_sock_t *sock);
|
||||
bool mme_is_maximum_number_of_enbs_reached(void);
|
||||
|
||||
enb_ue_t *enb_ue_add(mme_enb_t *enb, uint32_t enb_ue_s1ap_id);
|
||||
unsigned int enb_ue_count(void);
|
||||
|
@ -688,7 +682,7 @@ void mme_ue_remove_all(void);
|
|||
|
||||
mme_ue_t *mme_ue_find_by_imsi(uint8_t *imsi, int imsi_len);
|
||||
mme_ue_t *mme_ue_find_by_imsi_bcd(char *imsi_bcd);
|
||||
mme_ue_t *mme_ue_find_by_guti(ogs_nas_guti_t *nas_guti);
|
||||
mme_ue_t *mme_ue_find_by_guti(ogs_nas_eps_guti_t *nas_guti);
|
||||
mme_ue_t *mme_ue_find_by_teid(uint32_t teid);
|
||||
|
||||
mme_ue_t *mme_ue_find_by_message(ogs_nas_eps_message_t *message);
|
||||
|
@ -780,7 +774,7 @@ void mme_pdn_remove_all(mme_ue_t *mme_ue);
|
|||
ogs_pdn_t *mme_pdn_find_by_apn(mme_ue_t *mme_ue, char *apn);
|
||||
ogs_pdn_t *mme_default_pdn(mme_ue_t *mme_ue);
|
||||
|
||||
int mme_find_served_tai(ogs_tai_t *tai);
|
||||
int mme_find_served_tai(ogs_eps_tai_t *tai);
|
||||
|
||||
int mme_m_tmsi_pool_generate(void);
|
||||
mme_m_tmsi_t *mme_m_tmsi_alloc(void);
|
||||
|
|
|
@ -55,7 +55,7 @@ typedef enum {
|
|||
} mme_event_e;
|
||||
|
||||
typedef long S1AP_ProcedureCode_t;
|
||||
typedef struct S1AP_S1AP_PDU s1ap_message_t;
|
||||
typedef struct S1AP_S1AP_PDU ogs_s1ap_message_t;
|
||||
typedef struct ogs_nas_eps_message_s ogs_nas_eps_message_t;
|
||||
typedef struct mme_vlr_s mme_vlr_t;
|
||||
typedef struct mme_enb_s mme_enb_t;
|
||||
|
@ -77,7 +77,7 @@ typedef struct mme_event_s {
|
|||
uint16_t max_num_of_ostreams;
|
||||
|
||||
S1AP_ProcedureCode_t s1ap_code;
|
||||
s1ap_message_t *s1ap_message;
|
||||
ogs_s1ap_message_t *s1ap_message;
|
||||
|
||||
ogs_gtp_node_t *gnode;
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
|
|||
mme_enb_t *enb = NULL;
|
||||
uint16_t max_num_of_ostreams = 0;
|
||||
|
||||
s1ap_message_t s1ap_message;
|
||||
ogs_s1ap_message_t s1ap_message;
|
||||
ogs_pkbuf_t *pkbuf = NULL;
|
||||
int rc;
|
||||
|
||||
|
|
|
@ -40,7 +40,8 @@ static bool served_tai_is_found(mme_enb_t *enb)
|
|||
|
||||
for (i = 0; i < enb->num_of_supported_ta_list; i++) {
|
||||
served_tai_index = mme_find_served_tai(&enb->supported_ta_list[i]);
|
||||
if (served_tai_index >= 0 && served_tai_index < MAX_NUM_OF_SERVED_TAI) {
|
||||
if (served_tai_index >= 0 &&
|
||||
served_tai_index < OGS_MAX_NUM_OF_SERVED_TAI) {
|
||||
ogs_debug(" SERVED_TAI_INDEX[%d]", served_tai_index);
|
||||
return true;
|
||||
}
|
||||
|
@ -60,7 +61,7 @@ static bool maximum_number_of_enbs_is_reached(void)
|
|||
}
|
||||
}
|
||||
|
||||
return number_of_enbs_online >= ogs_config()->max.enb;
|
||||
return number_of_enbs_online >= ogs_config()->max.gnb;
|
||||
}
|
||||
|
||||
void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message)
|
||||
|
@ -256,13 +257,14 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message)
|
|||
/* Find MME_UE if S_TMSI included */
|
||||
if (S_TMSI) {
|
||||
served_gummei_t *served_gummei = &mme_self()->served_gummei[0];
|
||||
ogs_nas_guti_t nas_guti;
|
||||
ogs_nas_eps_guti_t nas_guti;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
|
||||
memset(&nas_guti, 0, sizeof(ogs_nas_guti_t));
|
||||
memset(&nas_guti, 0, sizeof(ogs_nas_eps_guti_t));
|
||||
|
||||
/* Use the first configured plmn_id and mme group id */
|
||||
ogs_nas_from_plmn_id(&nas_guti.nas_plmn_id, &served_gummei->plmn_id[0]);
|
||||
ogs_nas_from_plmn_id(&nas_guti.nas_plmn_id,
|
||||
&served_gummei->plmn_id[0]);
|
||||
nas_guti.mme_gid = served_gummei->mme_gid[0];
|
||||
|
||||
/* size must be 1 */
|
||||
|
@ -434,7 +436,7 @@ void s1ap_handle_ue_capability_info_indication(
|
|||
|
||||
if (enb_ue->mme_ue) {
|
||||
ogs_assert(UERadioCapability);
|
||||
OGS_S1AP_STORE_DATA(&enb_ue->mme_ue->ueRadioCapability,
|
||||
OGS_ASN_STORE_DATA(&enb_ue->mme_ue->ueRadioCapability,
|
||||
UERadioCapability);
|
||||
}
|
||||
}
|
||||
|
@ -1165,7 +1167,7 @@ void s1ap_handle_path_switch_request(
|
|||
enb_ue->saved.e_cgi.cell_id);
|
||||
|
||||
/* Copy TAI and ECGI from enb_ue */
|
||||
memcpy(&mme_ue->tai, &enb_ue->saved.tai, sizeof(ogs_tai_t));
|
||||
memcpy(&mme_ue->tai, &enb_ue->saved.tai, sizeof(ogs_eps_tai_t));
|
||||
memcpy(&mme_ue->e_cgi, &enb_ue->saved.e_cgi, sizeof(ogs_e_cgi_t));
|
||||
|
||||
memcpy(&eea, encryptionAlgorithms->buf, sizeof(eea));
|
||||
|
@ -1529,7 +1531,7 @@ void s1ap_handle_handover_request_ack(mme_enb_t *enb, ogs_s1ap_message_t *messag
|
|||
}
|
||||
}
|
||||
|
||||
OGS_S1AP_STORE_DATA(&mme_ue->container,
|
||||
OGS_ASN_STORE_DATA(&mme_ue->container,
|
||||
Target_ToSource_TransparentContainer);
|
||||
|
||||
if (mme_ue_have_indirect_tunnel(mme_ue) == 1) {
|
||||
|
@ -1858,7 +1860,7 @@ void s1ap_handle_handover_notification(mme_enb_t *enb, ogs_s1ap_message_t *messa
|
|||
target_ue->saved.e_cgi.cell_id);
|
||||
|
||||
/* Copy TAI and ECGI from enb_ue */
|
||||
memcpy(&mme_ue->tai, &target_ue->saved.tai, sizeof(ogs_tai_t));
|
||||
memcpy(&mme_ue->tai, &target_ue->saved.tai, sizeof(ogs_eps_tai_t));
|
||||
memcpy(&mme_ue->e_cgi, &target_ue->saved.e_cgi, sizeof(ogs_e_cgi_t));
|
||||
|
||||
sess = mme_sess_first(mme_ue);
|
||||
|
|
|
@ -350,7 +350,7 @@ void s1ap_send_paging(mme_ue_t *mme_ue, S1AP_CNDomain_t cn_domain)
|
|||
for (i = 0; i < enb->num_of_supported_ta_list; i++) {
|
||||
|
||||
if (memcmp(&enb->supported_ta_list[i], &mme_ue->tai,
|
||||
sizeof(ogs_tai_t)) == 0) {
|
||||
sizeof(ogs_eps_tai_t)) == 0) {
|
||||
|
||||
if (mme_ue->t3413.pkbuf) {
|
||||
s1apbuf = mme_ue->t3413.pkbuf;
|
||||
|
|
|
@ -35,7 +35,7 @@ void sbc_handle_write_replace_warning_request(sbc_pws_data_t *sbc_pws)
|
|||
for (i = 0, flag = 0; i < enb->num_of_supported_ta_list; i++) {
|
||||
for (j = 0; j < sbc_pws->no_of_tai; j++) {
|
||||
if (!memcmp(&enb->supported_ta_list[i],
|
||||
&sbc_pws->tai[j], sizeof(ogs_tai_t)))
|
||||
&sbc_pws->tai[j], sizeof(ogs_eps_tai_t)))
|
||||
flag = 1;
|
||||
|
||||
if (flag) break;
|
||||
|
@ -70,7 +70,7 @@ void sbc_handle_stop_warning_request(sbc_pws_data_t *sbc_pws)
|
|||
for (i = 0, flag = 0; i < enb->num_of_supported_ta_list; i++) {
|
||||
for (j = 0; j < sbc_pws->no_of_tai; j++) {
|
||||
if (!memcmp(&enb->supported_ta_list[i],
|
||||
&sbc_pws->tai[j], sizeof(ogs_tai_t)))
|
||||
&sbc_pws->tai[j], sizeof(ogs_eps_tai_t)))
|
||||
flag = 1;
|
||||
|
||||
if (flag) break;
|
||||
|
|
|
@ -38,7 +38,7 @@ typedef struct _sbc_pws_data_t {
|
|||
uint16_t message_id;
|
||||
uint16_t serial_number;
|
||||
uint32_t no_of_tai;
|
||||
ogs_tai_t tai[16]; /* TODO: max 65535 */
|
||||
ogs_eps_tai_t tai[16]; /* TODO: max 65535 */
|
||||
uint32_t repetition_period;
|
||||
uint32_t number_of_broadcast;
|
||||
uint8_t data_coding_scheme;
|
||||
|
|
|
@ -125,7 +125,7 @@ typedef struct sgw_bearer_s {
|
|||
uint8_t ebi;
|
||||
|
||||
/* User-Lication-Info */
|
||||
ogs_tai_t tai;
|
||||
ogs_eps_tai_t tai;
|
||||
ogs_e_cgi_t e_cgi;
|
||||
|
||||
/* Pkts which will be buffered in case of UE-IDLE */
|
||||
|
|
|
@ -503,7 +503,7 @@ int smf_context_parse_config(void)
|
|||
} else if (!strcmp(smf_key, "pdn")) {
|
||||
/* handle config in pfcp library */
|
||||
} else if (!strcmp(smf_key, "sbi")) {
|
||||
/* handle config in pfcp library */
|
||||
/* handle config in sbi library */
|
||||
} else
|
||||
ogs_warn("unknown key `%s`", smf_key);
|
||||
}
|
||||
|
|
|
@ -201,11 +201,12 @@ void smf_nf_state_registered(ogs_fsm_t *s, smf_event_t *e)
|
|||
|
||||
switch (e->id) {
|
||||
case OGS_FSM_ENTRY_SIG:
|
||||
client = nf_instance->client;
|
||||
ogs_assert(client);
|
||||
if (NF_INSTANCE_IS_SELF(nf_instance->id)) {
|
||||
ogs_info("NF registered [%s]", nf_instance->id);
|
||||
|
||||
client = nf_instance->client;
|
||||
ogs_assert(client);
|
||||
|
||||
if (nf_instance->time.heartbeat) {
|
||||
ogs_timer_start(nf_instance->t_heartbeat_interval,
|
||||
ogs_time_from_sec(nf_instance->time.heartbeat));
|
||||
|
|
|
@ -153,18 +153,8 @@ bool smf_nnrf_handle_nf_status_notify(ogs_sbi_server_t *server,
|
|||
if (!nf_instance) {
|
||||
nf_instance = ogs_sbi_nf_instance_add(NFProfile->nf_instance_id);
|
||||
ogs_assert(nf_instance);
|
||||
|
||||
smf_nf_fsm_init(nf_instance);
|
||||
|
||||
client = ogs_sbi_nf_instance_find_client(nf_instance);
|
||||
if (!client) {
|
||||
ogs_error("Cannot find client [%s]", nf_instance->id);
|
||||
ogs_sbi_server_send_error(session,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
message, "Cannot find client", nf_instance->id);
|
||||
return false;
|
||||
}
|
||||
smf_sbi_nf_associate_client(nf_instance, client);
|
||||
|
||||
ogs_info("(NRF-notify) NF registered [%s]", nf_instance->id);
|
||||
} else
|
||||
ogs_warn("(NRF-notify) NF [%s] has already been added",
|
||||
|
@ -176,6 +166,15 @@ bool smf_nnrf_handle_nf_status_notify(ogs_sbi_server_t *server,
|
|||
|
||||
ogs_info("(NRF-notify) NF Profile updated [%s]", nf_instance->id);
|
||||
|
||||
client = ogs_sbi_nf_instance_find_client(nf_instance);
|
||||
if (!client) {
|
||||
ogs_error("Cannot find client [%s]", nf_instance->id);
|
||||
ogs_sbi_server_send_error(session,
|
||||
OGS_SBI_HTTP_STATUS_BAD_REQUEST,
|
||||
message, "Cannot find client", nf_instance->id);
|
||||
return false;
|
||||
}
|
||||
smf_sbi_nf_associate_client(nf_instance, client);
|
||||
|
||||
} else if (NotificationData->event ==
|
||||
OpenAPI_notification_event_type_NF_DEREGISTERED) {
|
||||
|
@ -186,9 +185,13 @@ bool smf_nnrf_handle_nf_status_notify(ogs_sbi_server_t *server,
|
|||
ogs_sbi_nf_instance_remove(nf_instance);
|
||||
|
||||
/* FIXME : Remove unnecessary Client */
|
||||
} else
|
||||
ogs_warn("(NRF-notify) NF [%s] has already been removed",
|
||||
NFProfile->nf_instance_id);
|
||||
} else {
|
||||
ogs_warn("(NRF-notify) Not found [%s]", NFProfile->nf_instance_id);
|
||||
ogs_sbi_server_send_error(session,
|
||||
OGS_SBI_HTTP_STATUS_NOT_FOUND,
|
||||
message, "Not found", message->h.resource.id);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
char *eventstr = OpenAPI_notification_event_type_ToString(
|
||||
NotificationData->event);
|
||||
|
@ -235,18 +238,11 @@ void smf_nnrf_handle_nf_discover(ogs_sbi_message_t *message)
|
|||
if (!nf_instance) {
|
||||
nf_instance = ogs_sbi_nf_instance_add(NFProfile->nf_instance_id);
|
||||
ogs_assert(nf_instance);
|
||||
|
||||
smf_nf_fsm_init(nf_instance);
|
||||
|
||||
client = ogs_sbi_nf_instance_find_client(nf_instance);
|
||||
if (!client) {
|
||||
ogs_error("Cannot find client [%s]", nf_instance->id);
|
||||
continue;
|
||||
}
|
||||
smf_sbi_nf_associate_client(nf_instance, client);
|
||||
|
||||
ogs_info("(NF-Discover) NF registered [%s]", nf_instance->id);
|
||||
ogs_info("(NF-discover) NF registered [%s]", nf_instance->id);
|
||||
} else
|
||||
ogs_warn("(NF-Discover) NF [%s] has already been added",
|
||||
ogs_warn("(NF-discover) NF [%s] has already been added",
|
||||
NFProfile->nf_instance_id);
|
||||
|
||||
if (NF_INSTANCE_IS_OTHERS(nf_instance->id)) {
|
||||
|
@ -276,7 +272,7 @@ void smf_nnrf_handle_nf_discover(ogs_sbi_message_t *message)
|
|||
} else
|
||||
ogs_warn("NF Instance validity-time should not 0");
|
||||
|
||||
ogs_info("(NF-Discover) NF Profile updated [%s]", nf_instance->id);
|
||||
ogs_info("(NF-discover) NF Profile updated [%s]", nf_instance->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "test-5gc.h"
|
||||
|
||||
static ogs_thread_t *nrf_thread = NULL;
|
||||
static ogs_thread_t *smf_thread = NULL;
|
||||
static ogs_thread_t *upf_thread = NULL;
|
||||
#if 0
|
||||
static ogs_thread_t *amf_thread = NULL;
|
||||
#endif
|
||||
|
||||
int app_initialize(const char *const argv[])
|
||||
{
|
||||
int rv;
|
||||
|
||||
const char *argv_out[OGS_ARG_MAX];
|
||||
bool user_config = false;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; argv[i]; i++) {
|
||||
if (strcmp("-c", argv[i]) == 0) {
|
||||
user_config = true;
|
||||
}
|
||||
argv_out[i] = argv[i];
|
||||
}
|
||||
argv_out[i] = NULL;
|
||||
|
||||
if (!user_config) {
|
||||
argv_out[i++] = "-c";
|
||||
argv_out[i++] = DEFAULT_CONFIG_FILENAME;
|
||||
argv_out[i] = NULL;
|
||||
}
|
||||
|
||||
if (ogs_config()->parameter.no_nrf == 0)
|
||||
nrf_thread = test_child_create("nrf", argv_out);
|
||||
if (ogs_config()->parameter.no_upf == 0)
|
||||
upf_thread = test_child_create("upf", argv_out);
|
||||
if (ogs_config()->parameter.no_smf == 0)
|
||||
smf_thread = test_child_create("smf", argv_out);
|
||||
|
||||
ogs_sctp_init(ogs_config()->usrsctp.udp_port);
|
||||
|
||||
rv = amf_initialize();
|
||||
ogs_assert(rv == OGS_OK);
|
||||
ogs_info("AMF initialize...done");
|
||||
|
||||
return OGS_OK;;
|
||||
}
|
||||
|
||||
void app_terminate(void)
|
||||
{
|
||||
amf_terminate();
|
||||
|
||||
ogs_sctp_final();
|
||||
ogs_info("AMF terminate...done");
|
||||
|
||||
if (smf_thread) ogs_thread_destroy(smf_thread);
|
||||
if (upf_thread) ogs_thread_destroy(upf_thread);
|
||||
if (nrf_thread) ogs_thread_destroy(nrf_thread);
|
||||
}
|
||||
|
||||
void test_5gc_init(void)
|
||||
{
|
||||
ogs_log_install_domain(&__ogs_sctp_domain, "sctp", OGS_LOG_ERROR);
|
||||
ogs_log_install_domain(&__ogs_ngap_domain, "ngap", OGS_LOG_ERROR);
|
||||
ogs_log_install_domain(&__ogs_dbi_domain, "dbi", OGS_LOG_ERROR);
|
||||
ogs_log_install_domain(&__ogs_nas_domain, "nas", OGS_LOG_ERROR);
|
||||
ogs_log_install_domain(&__ogs_sbi_domain, "sbi", OGS_LOG_ERROR);
|
||||
|
||||
ogs_assert(ogs_mongoc_init(ogs_config()->db_uri) == OGS_OK);
|
||||
}
|
|
@ -17,86 +17,13 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ogs-sctp.h"
|
||||
|
||||
#include "test-epc.h"
|
||||
#include "test-config-private.h"
|
||||
|
||||
#define MAX_CHILD_PROCESS 8
|
||||
#define OGS_ARG_MAX 256
|
||||
|
||||
static ogs_thread_t *pcrf_thread = NULL;
|
||||
static ogs_thread_t *pgw_thread = NULL;
|
||||
static ogs_thread_t *sgw_thread = NULL;
|
||||
static ogs_thread_t *hss_thread = NULL;
|
||||
|
||||
static ogs_proc_t process[MAX_CHILD_PROCESS];
|
||||
static int process_num = 0;
|
||||
|
||||
static void child_main(void *data)
|
||||
{
|
||||
const char **commandLine = data;
|
||||
ogs_proc_t *current = NULL;
|
||||
FILE *out = NULL;
|
||||
char buf[OGS_HUGE_LEN];
|
||||
int ret = 0, out_return_code = 0;;
|
||||
|
||||
current = &process[process_num++];
|
||||
ret = ogs_proc_create(commandLine,
|
||||
ogs_proc_option_combined_stdout_stderr|
|
||||
ogs_proc_option_inherit_environment,
|
||||
current);
|
||||
ogs_assert(ret == 0);
|
||||
out = ogs_proc_stdout(current);
|
||||
ogs_assert(out);
|
||||
|
||||
while(fgets(buf, OGS_HUGE_LEN, out)) {
|
||||
printf("%s", buf);
|
||||
}
|
||||
|
||||
ret = ogs_proc_join(current, &out_return_code);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_assert(out_return_code == 0);
|
||||
|
||||
ret = ogs_proc_destroy(current);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
ogs_thread_t *test_child_create(const char *name, const char *const argv[])
|
||||
{
|
||||
ogs_thread_t *child = NULL;
|
||||
const char *commandLine[OGS_ARG_MAX];
|
||||
int i = 0;
|
||||
char command[OGS_MAX_FILEPATH_LEN];
|
||||
|
||||
while(argv[i] && i < 32) {
|
||||
commandLine[i] = argv[i];
|
||||
i++;
|
||||
}
|
||||
commandLine[i] = NULL;
|
||||
|
||||
/* buildroot/src/mme/open5gs-mmed */
|
||||
ogs_snprintf(command, sizeof command, "%s%s%s%sd",
|
||||
MESON_BUILD_ROOT OGS_DIR_SEPARATOR_S "src" OGS_DIR_SEPARATOR_S,
|
||||
name, OGS_DIR_SEPARATOR_S "open5gs-", name);
|
||||
commandLine[0] = command;
|
||||
|
||||
child = ogs_thread_create(child_main, commandLine);
|
||||
ogs_msleep(50);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
void test_child_terminate(void)
|
||||
{
|
||||
int i;
|
||||
ogs_proc_t *current = NULL;
|
||||
for (i = 0; i < process_num; i++) {
|
||||
current = &process[i];
|
||||
ogs_proc_terminate(current);
|
||||
}
|
||||
}
|
||||
|
||||
int app_initialize(const char *const argv[])
|
||||
{
|
||||
int rv;
|
||||
|
@ -149,3 +76,14 @@ void app_terminate(void)
|
|||
if (pgw_thread) ogs_thread_destroy(pgw_thread);
|
||||
if (pcrf_thread) ogs_thread_destroy(pcrf_thread);
|
||||
}
|
||||
|
||||
void test_epc_init(void)
|
||||
{
|
||||
ogs_log_install_domain(&__ogs_sctp_domain, "sctp", OGS_LOG_ERROR);
|
||||
ogs_log_install_domain(&__ogs_s1ap_domain, "s1ap", OGS_LOG_ERROR);
|
||||
ogs_log_install_domain(&__ogs_diam_domain, "diam", OGS_LOG_ERROR);
|
||||
ogs_log_install_domain(&__ogs_dbi_domain, "dbi", OGS_LOG_ERROR);
|
||||
ogs_log_install_domain(&__ogs_nas_domain, "nas", OGS_LOG_ERROR);
|
||||
|
||||
ogs_assert(ogs_mongoc_init(ogs_config()->db_uri) == OGS_OK);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
# Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
|
||||
# This file is part of Open5GS.
|
||||
|
||||
|
@ -14,25 +14,77 @@
|
|||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
libtestapp_sources = files('''
|
||||
test-packet.h
|
||||
test-app.h
|
||||
|
||||
test-packet.c
|
||||
test-app.c
|
||||
'''.split())
|
||||
#
|
||||
|
||||
libtestapp_inc = include_directories('.')
|
||||
|
||||
libtestapp = static_library('testapp',
|
||||
sources : libtestapp_sources,
|
||||
c_args : testcore_cc_flags,
|
||||
include_directories : libtestapp_inc,
|
||||
dependencies : libtestepc_dep,
|
||||
libtestepc_cc_args = '-DDEFAULT_CONFIG_FILENAME="@0@/configs/epc.yaml"'.format(meson.build_root())
|
||||
|
||||
libtestepc_sources = files('''
|
||||
test-packet.c
|
||||
epc-init.c
|
||||
'''.split())
|
||||
|
||||
libtestepc = static_library('testepc',
|
||||
sources : [libtestepc_sources],
|
||||
c_args : libtestepc_cc_args,
|
||||
include_directories : [libtestapp_inc, srcinc],
|
||||
link_with : [libmme, libhss, libsgw, libpgw, libpcrf],
|
||||
dependencies : [libtestcommon_dep,
|
||||
libmme_dep,
|
||||
libhss_dep,
|
||||
libsgw_dep,
|
||||
libpgw_dep,
|
||||
libpcrf_dep],
|
||||
install : false)
|
||||
|
||||
libtestapp_dep = declare_dependency(
|
||||
link_with : libtestapp,
|
||||
include_directories : libtestapp_inc,
|
||||
dependencies : libtestepc_dep)
|
||||
libtestepc_dep = declare_dependency(
|
||||
link_with : libtestepc,
|
||||
include_directories : [libtestapp_inc, srcinc],
|
||||
dependencies : [libtestcommon_dep,
|
||||
libmme_dep,
|
||||
libhss_dep,
|
||||
libsgw_dep,
|
||||
libpgw_dep,
|
||||
libpcrf_dep])
|
||||
|
||||
testepc_sources = files('''
|
||||
../../src/main.c
|
||||
'''.split())
|
||||
|
||||
executable('epc',
|
||||
sources : [testepc_sources],
|
||||
c_args : libtestepc_cc_args,
|
||||
include_directories : srcinc,
|
||||
dependencies : [libtestepc_dep])
|
||||
|
||||
libtest5gc_cc_args = '-DDEFAULT_CONFIG_FILENAME="@0@/configs/5gc.yaml"'.format(meson.build_root())
|
||||
|
||||
libtest5gc_sources = files('''
|
||||
5gc-init.c
|
||||
'''.split())
|
||||
|
||||
libtest5gc = static_library('test5gc',
|
||||
sources : [libtest5gc_sources],
|
||||
c_args : libtest5gc_cc_args,
|
||||
include_directories : [libtestapp_inc, srcinc],
|
||||
link_with : libamf,
|
||||
dependencies : [libtestcommon_dep,
|
||||
libamf_dep],
|
||||
install : false)
|
||||
|
||||
libtest5gc_dep = declare_dependency(
|
||||
link_with : libtest5gc,
|
||||
include_directories : [libtestapp_inc, srcinc],
|
||||
dependencies : [libtestcommon_dep,
|
||||
libamf_dep])
|
||||
|
||||
test5gc_sources = files('''
|
||||
../../src/main.c
|
||||
'''.split())
|
||||
|
||||
executable('5gc',
|
||||
sources : [test5gc_sources],
|
||||
c_args : libtest5gc_cc_args,
|
||||
include_directories : srcinc,
|
||||
dependencies : [libtest5gc_dep])
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TEST_5GC_H
|
||||
#define TEST_5GC_H
|
||||
|
||||
#include "test-common.h"
|
||||
#include "test-ngap.h"
|
||||
|
||||
#include "amf/context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void test_5gc_init(void);
|
||||
#define test_5gc_final ogs_mongoc_final
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TEST_5GC_H */
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "test-app.h"
|
||||
#include "test-config-private.h"
|
||||
|
||||
static int connected_count = 0;
|
||||
static void test_diam_logger_handler(enum fd_hook_type type, struct msg * msg,
|
||||
struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd,
|
||||
void * regdata)
|
||||
{
|
||||
if (type == HOOK_PEER_CONNECT_SUCCESS) {
|
||||
connected_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void test_app_run(int argc, const char *const argv[],
|
||||
const char *name, void (*init)(const char * const argv[]))
|
||||
{
|
||||
int rv;
|
||||
bool user_config;
|
||||
|
||||
/* '-f sample-XXXX.conf -e error' is always added */
|
||||
const char *argv_out[argc+4], *new_argv[argc+4];
|
||||
int argc_out;
|
||||
|
||||
char conf_file[OGS_MAX_FILEPATH_LEN];
|
||||
|
||||
user_config = false;
|
||||
for (argc_out = 0; argc_out < argc; argc_out++) {
|
||||
if (strcmp("-c", argv[argc_out]) == 0) {
|
||||
user_config = true;
|
||||
}
|
||||
argv_out[argc_out] = argv[argc_out];
|
||||
}
|
||||
argv_out[argc_out] = NULL;
|
||||
|
||||
if (!user_config) {
|
||||
/* buildroot/configs/XXX-conf.yaml */
|
||||
ogs_snprintf(conf_file, sizeof conf_file, "%s%s",
|
||||
MESON_BUILD_ROOT OGS_DIR_SEPARATOR_S
|
||||
"configs" OGS_DIR_SEPARATOR_S, name);
|
||||
argv_out[argc_out++] = "-c";
|
||||
argv_out[argc_out++] = conf_file;
|
||||
argv_out[argc_out] = NULL;
|
||||
}
|
||||
|
||||
/* buildroot/src/open5gs-main */
|
||||
argv_out[0] = MESON_BUILD_ROOT OGS_DIR_SEPARATOR_S
|
||||
"src" OGS_DIR_SEPARATOR_S "open5gs-main";
|
||||
|
||||
rv = abts_main(argc_out, argv_out, new_argv);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
ogs_diam_logger_register(test_diam_logger_handler);
|
||||
|
||||
(*init)(new_argv);
|
||||
|
||||
while(1) {
|
||||
if (connected_count == 1) break;
|
||||
ogs_msleep(50);
|
||||
}
|
||||
|
||||
ogs_msleep(500); /* Wait for listening all sockets */
|
||||
}
|
||||
|
||||
void test_app_init(void)
|
||||
{
|
||||
ogs_log_install_domain(&__ogs_sctp_domain, "sctp", OGS_LOG_ERROR);
|
||||
ogs_log_install_domain(&__ogs_s1ap_domain, "s1ap", OGS_LOG_ERROR);
|
||||
ogs_log_install_domain(&__ogs_diam_domain, "diam", OGS_LOG_ERROR);
|
||||
ogs_log_install_domain(&__ogs_dbi_domain, "dbi", OGS_LOG_ERROR);
|
||||
ogs_log_install_domain(&__ogs_nas_domain, "nas", OGS_LOG_ERROR);
|
||||
|
||||
ogs_assert(ogs_mongoc_init(ogs_config()->db_uri) == OGS_OK);
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef TEST_APP_H
|
||||
#define TEST_APP_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ogs-diameter-common.h"
|
||||
#include "ogs-sctp.h"
|
||||
#include "ogs-dbi.h"
|
||||
#include "ogs-app.h"
|
||||
#include "mme/mme-context.h"
|
||||
#include "core/abts.h"
|
||||
|
||||
#include "test-epc.h"
|
||||
#include "test-packet.h"
|
||||
|
||||
void test_app_run(int argc, const char *const argv[],
|
||||
const char *name, void (*init)(const char * const argv[]));
|
||||
|
||||
void test_app_init(void);
|
||||
#define test_app_final ogs_mongoc_final
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TEST_APP_H */
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TEST_EPC_H
|
||||
#define TEST_EPC_H
|
||||
|
||||
#include "test-packet.h"
|
||||
|
||||
#include "mme/mme-context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void test_epc_init(void);
|
||||
#define test_epc_final ogs_mongoc_final
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TEST_EPC_H */
|
|
@ -44,128 +44,13 @@
|
|||
|
||||
#include "mme/sgsap-path.h"
|
||||
|
||||
ogs_socknode_t *testsctp_server(const char *ipstr)
|
||||
{
|
||||
int rv;
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
ogs_socknode_t *node = NULL;
|
||||
|
||||
rv = ogs_getaddrinfo(&addr, AF_UNSPEC, ipstr, OGS_SGSAP_SCTP_PORT, 0);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
node = ogs_socknode_new(addr);
|
||||
ogs_assert(node);
|
||||
ogs_socknode_nodelay(node, true);
|
||||
|
||||
ogs_sctp_server(SOCK_SEQPACKET, node);
|
||||
ogs_assert(node->sock);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
ogs_socknode_t *testsctp_client(const char *ipstr)
|
||||
{
|
||||
int rv;
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
ogs_socknode_t *node = NULL;
|
||||
|
||||
rv = ogs_getaddrinfo(&addr, AF_UNSPEC, ipstr, OGS_S1AP_SCTP_PORT, 0);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
node = ogs_socknode_new(addr);
|
||||
ogs_assert(node);
|
||||
ogs_socknode_nodelay(node, true);
|
||||
|
||||
ogs_sctp_client(SOCK_STREAM, node);
|
||||
ogs_assert(node->sock);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static ogs_sockaddr_t sctp_last_addr;
|
||||
|
||||
ogs_pkbuf_t *testsctp_read(ogs_socknode_t *node, int type)
|
||||
{
|
||||
int size;
|
||||
ogs_pkbuf_t *recvbuf = NULL;
|
||||
|
||||
ogs_assert(node);
|
||||
ogs_assert(node->sock);
|
||||
|
||||
recvbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
||||
ogs_pkbuf_put(recvbuf, OGS_MAX_SDU_LEN);
|
||||
|
||||
size = ogs_sctp_recvdata(node->sock, recvbuf->data, OGS_MAX_SDU_LEN,
|
||||
type == 1 ? &sctp_last_addr : NULL, NULL);
|
||||
if (size <= 0) {
|
||||
ogs_error("sgsap_recv() failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ogs_pkbuf_trim(recvbuf, size);
|
||||
return recvbuf;;
|
||||
}
|
||||
|
||||
int testenb_s1ap_send(ogs_socknode_t *node, ogs_pkbuf_t *sendbuf)
|
||||
{
|
||||
return s1ap_send(node->sock, sendbuf, NULL, 0);
|
||||
}
|
||||
|
||||
int testvlr_sgsap_send(ogs_socknode_t *node, ogs_pkbuf_t *sendbuf)
|
||||
{
|
||||
return sgsap_send(node->sock, sendbuf, &sctp_last_addr, 0);
|
||||
}
|
||||
|
||||
ogs_socknode_t *testenb_gtpu_server(const char *ipstr)
|
||||
{
|
||||
int rv;
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
ogs_socknode_t *node = NULL;
|
||||
ogs_sock_t *sock = NULL;
|
||||
|
||||
rv = ogs_getaddrinfo(&addr, AF_UNSPEC, ipstr, OGS_GTPV1_U_UDP_PORT, 0);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
node = ogs_socknode_new(addr);
|
||||
ogs_assert(node);
|
||||
|
||||
sock = ogs_udp_server(node);
|
||||
ogs_assert(sock);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *testenb_gtpu_read(ogs_socknode_t *node)
|
||||
{
|
||||
int rc = 0;
|
||||
ogs_pkbuf_t *recvbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
||||
ogs_pkbuf_put(recvbuf, OGS_MAX_SDU_LEN);
|
||||
|
||||
ogs_assert(node);
|
||||
ogs_assert(node->sock);
|
||||
|
||||
while (1) {
|
||||
rc = ogs_recv(node->sock->fd, recvbuf->data, recvbuf->len, 0);
|
||||
if (rc <= 0) {
|
||||
if (errno == EAGAIN) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
recvbuf->len = rc;
|
||||
|
||||
return recvbuf;
|
||||
}
|
||||
#include "test-packet.h"
|
||||
|
||||
bool test_no_mme_self = 0;
|
||||
|
||||
int testenb_gtpu_send(ogs_socknode_t *node, ogs_pkbuf_t *sendbuf)
|
||||
{
|
||||
int rv;
|
||||
ogs_hash_index_t *hi = NULL;
|
||||
mme_ue_t *mme_ue = NULL;
|
||||
mme_sess_t *sess = NULL;
|
||||
mme_bearer_t *bearer = NULL;
|
||||
|
@ -213,17 +98,10 @@ int testenb_gtpu_send(ogs_socknode_t *node, ogs_pkbuf_t *sendbuf)
|
|||
return OGS_OK;
|
||||
}
|
||||
|
||||
void testenb_gtpu_close(ogs_socknode_t *node)
|
||||
{
|
||||
ogs_socknode_free(node);
|
||||
}
|
||||
|
||||
int tests1ap_build_setup_req(
|
||||
ogs_pkbuf_t **pkbuf, S1AP_ENB_ID_PR present, uint32_t enb_id,
|
||||
int tac, uint16_t mcc, uint16_t mnc, uint16_t mnc_len)
|
||||
{
|
||||
int rv;
|
||||
|
||||
ogs_plmn_id_t plmn_id;
|
||||
|
||||
S1AP_S1AP_PDU_t pdu;
|
||||
|
@ -1187,12 +1065,9 @@ int tests1ap_build_ue_context_modification_response(
|
|||
ogs_pkbuf_t **pkbuf,
|
||||
uint32_t mme_ue_s1ap_id, uint32_t enb_ue_s1ap_id)
|
||||
{
|
||||
int rv;
|
||||
|
||||
S1AP_S1AP_PDU_t pdu;
|
||||
S1AP_SuccessfulOutcome_t *successfulOutcome = NULL;
|
||||
S1AP_UEContextModificationResponse_t *UEContextModificationResponse = NULL;
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
|
||||
S1AP_UEContextModificationResponseIEs_t *ie = NULL;
|
||||
S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL;
|
||||
|
@ -2480,8 +2355,6 @@ static void build_bearer_resource_modification_request(ogs_pkbuf_t **pkbuf,
|
|||
|
||||
ogs_gtp_tft_t tft;
|
||||
ogs_tlv_octet_t octet;
|
||||
int len;
|
||||
char tft_buf[OGS_GTP_MAX_TRAFFIC_FLOW_TEMPLATE];
|
||||
ogs_ipsubnet_t ipsubnet;
|
||||
|
||||
memset(&message, 0, sizeof(message));
|
||||
|
@ -2669,7 +2542,6 @@ int tests1ap_build_bearer_resource_modification_request(
|
|||
uint8_t tft_code, uint8_t qci,
|
||||
uint8_t ul_mbr, uint8_t dl_mbr, uint8_t ul_gbr, uint8_t dl_gbr)
|
||||
{
|
||||
int rv;
|
||||
ogs_pkbuf_t *emmbuf = NULL;
|
||||
|
||||
S1AP_S1AP_PDU_t pdu;
|
||||
|
@ -2680,8 +2552,6 @@ int tests1ap_build_bearer_resource_modification_request(
|
|||
S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL;
|
||||
S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL;
|
||||
S1AP_NAS_PDU_t *NAS_PDU = NULL;
|
||||
S1AP_EUTRAN_CGI_t *EUTRAN_CGI = NULL;
|
||||
S1AP_TAI_t *TAI = NULL;
|
||||
|
||||
memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t));
|
||||
pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage;
|
||||
|
@ -3070,8 +2940,6 @@ int tests1ap_build_handover_request_ack(
|
|||
S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL;
|
||||
S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL;
|
||||
S1AP_E_RABAdmittedList_t *E_RABAdmittedList = NULL;
|
||||
S1AP_E_RABFailedtoSetupListHOReqAck_t
|
||||
*E_RABFailedtoSetupListHOReqAck = NULL;
|
||||
S1AP_Target_ToSource_TransparentContainer_t
|
||||
*Target_ToSource_TransparentContainer = NULL;
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
|
||||
#include "ogs-s1ap.h"
|
||||
#include "mme/s1ap-build.h"
|
||||
#include "core/abts.h"
|
||||
|
||||
#include "test-common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -30,24 +31,10 @@ extern "C" {
|
|||
|
||||
extern bool test_no_mme_self;
|
||||
|
||||
ogs_socknode_t *testsctp_server(const char *ipstr);
|
||||
ogs_socknode_t *testsctp_client(const char *ipstr);
|
||||
ogs_pkbuf_t *testsctp_read(ogs_socknode_t *node, int type);
|
||||
|
||||
#define testenb_s1ap_client testsctp_client
|
||||
#define testenb_s1ap_read(x) testsctp_read(x, 0);
|
||||
int testenb_s1ap_send(ogs_socknode_t *node, ogs_pkbuf_t *sendbuf);
|
||||
#define testenb_s1ap_close ogs_socknode_free
|
||||
|
||||
#define testvlr_sgsap_server testsctp_server
|
||||
#define testvlr_sgsap_read(x) testsctp_read(x, 1);
|
||||
int testvlr_sgsap_send(ogs_socknode_t *node, ogs_pkbuf_t *sendbuf);
|
||||
#define testvlr_sgsap_close ogs_socknode_free
|
||||
|
||||
ogs_socknode_t *testenb_gtpu_server(const char *ipstr);
|
||||
ogs_pkbuf_t *testenb_gtpu_read(ogs_socknode_t *node);
|
||||
#define testenb_gtpu_server(x) test_gtpu_server(x, OGS_GTPV1_U_UDP_PORT)
|
||||
#define testenb_gtpu_read(x) test_gtpu_read(x)
|
||||
int testenb_gtpu_send(ogs_socknode_t *node, ogs_pkbuf_t *sendbuf);
|
||||
void testenb_gtpu_close(ogs_socknode_t *node);
|
||||
#define testenb_gtpu_close(x) test_gtpu_close(x)
|
||||
|
||||
int tests1ap_build_invalid_packet(ogs_pkbuf_t **pkbuf, int i);
|
||||
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "test-config-private.h"
|
||||
#include "test-common.h"
|
||||
|
||||
static int connected_count = 0;
|
||||
static void test_diam_logger_handler(enum fd_hook_type type, struct msg * msg,
|
||||
struct peer_hdr * peer, void * other, struct fd_hook_permsgdata *pmd,
|
||||
void * regdata)
|
||||
{
|
||||
if (type == HOOK_PEER_CONNECT_SUCCESS) {
|
||||
connected_count++;
|
||||
}
|
||||
}
|
||||
|
||||
static void test_app_run(int argc, const char *const argv[],
|
||||
const char *name, void (*init)(const char * const argv[]))
|
||||
{
|
||||
int rv;
|
||||
bool user_config;
|
||||
|
||||
/* '-f sample-XXXX.conf -e error' is always added */
|
||||
const char *argv_out[argc+4], *new_argv[argc+4];
|
||||
int argc_out;
|
||||
|
||||
char conf_file[OGS_MAX_FILEPATH_LEN];
|
||||
|
||||
user_config = false;
|
||||
for (argc_out = 0; argc_out < argc; argc_out++) {
|
||||
if (strcmp("-c", argv[argc_out]) == 0) {
|
||||
user_config = true;
|
||||
}
|
||||
argv_out[argc_out] = argv[argc_out];
|
||||
}
|
||||
argv_out[argc_out] = NULL;
|
||||
|
||||
if (!user_config) {
|
||||
/* buildroot/configs/XXX-conf.yaml */
|
||||
ogs_snprintf(conf_file, sizeof conf_file, "%s%s",
|
||||
MESON_BUILD_ROOT OGS_DIR_SEPARATOR_S
|
||||
"configs" OGS_DIR_SEPARATOR_S, name);
|
||||
argv_out[argc_out++] = "-c";
|
||||
argv_out[argc_out++] = conf_file;
|
||||
argv_out[argc_out] = NULL;
|
||||
}
|
||||
|
||||
/* buildroot/src/open5gs-main */
|
||||
argv_out[0] = MESON_BUILD_ROOT OGS_DIR_SEPARATOR_S
|
||||
"src" OGS_DIR_SEPARATOR_S "open5gs-main";
|
||||
|
||||
rv = abts_main(argc_out, argv_out, new_argv);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
(*init)(new_argv);
|
||||
}
|
||||
|
||||
void test_epc_run(int argc, const char *const argv[],
|
||||
const char *name, void (*init)(const char * const argv[]))
|
||||
{
|
||||
ogs_diam_logger_register(test_diam_logger_handler);
|
||||
|
||||
test_app_run(argc, argv, name, init);
|
||||
|
||||
while(1) {
|
||||
if (connected_count == 1) break;
|
||||
ogs_msleep(50);
|
||||
}
|
||||
|
||||
ogs_msleep(500); /* Wait for listening all sockets */
|
||||
}
|
||||
|
||||
void test_5gc_run(int argc, const char *const argv[],
|
||||
const char *name, void (*init)(const char * const argv[]))
|
||||
{
|
||||
int rv;
|
||||
|
||||
test_app_run(argc, argv, name, init);
|
||||
|
||||
test_context_init();
|
||||
|
||||
rv = test_context_parse_config();
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
ogs_msleep(500); /* Wait for listening all sockets */
|
||||
}
|
||||
|
||||
#define MAX_CHILD_PROCESS 8
|
||||
#define OGS_ARG_MAX 256
|
||||
|
||||
static ogs_proc_t process[MAX_CHILD_PROCESS];
|
||||
static int process_num = 0;
|
||||
|
||||
static void child_main(void *data)
|
||||
{
|
||||
const char **commandLine = data;
|
||||
ogs_proc_t *current = NULL;
|
||||
FILE *out = NULL;
|
||||
char buf[OGS_HUGE_LEN];
|
||||
int ret = 0, out_return_code = 0;;
|
||||
|
||||
current = &process[process_num++];
|
||||
ret = ogs_proc_create(commandLine,
|
||||
ogs_proc_option_combined_stdout_stderr|
|
||||
ogs_proc_option_inherit_environment,
|
||||
current);
|
||||
ogs_assert(ret == 0);
|
||||
out = ogs_proc_stdout(current);
|
||||
ogs_assert(out);
|
||||
|
||||
while(fgets(buf, OGS_HUGE_LEN, out)) {
|
||||
printf("%s", buf);
|
||||
}
|
||||
|
||||
ret = ogs_proc_join(current, &out_return_code);
|
||||
ogs_assert(ret == 0);
|
||||
ogs_assert(out_return_code == 0);
|
||||
|
||||
ret = ogs_proc_destroy(current);
|
||||
ogs_assert(ret == 0);
|
||||
}
|
||||
|
||||
ogs_thread_t *test_child_create(const char *name, const char *const argv[])
|
||||
{
|
||||
ogs_thread_t *child = NULL;
|
||||
const char *commandLine[OGS_ARG_MAX];
|
||||
int i = 0;
|
||||
char command[OGS_MAX_FILEPATH_LEN];
|
||||
|
||||
while(argv[i] && i < 32) {
|
||||
commandLine[i] = argv[i];
|
||||
i++;
|
||||
}
|
||||
commandLine[i] = NULL;
|
||||
|
||||
/* buildroot/src/mme/open5gs-mmed */
|
||||
ogs_snprintf(command, sizeof command, "%s%s%s%sd",
|
||||
MESON_BUILD_ROOT OGS_DIR_SEPARATOR_S "src" OGS_DIR_SEPARATOR_S,
|
||||
name, OGS_DIR_SEPARATOR_S "open5gs-", name);
|
||||
commandLine[0] = command;
|
||||
|
||||
child = ogs_thread_create(child_main, commandLine);
|
||||
ogs_msleep(50);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
void test_child_terminate(void)
|
||||
{
|
||||
int i;
|
||||
ogs_proc_t *current = NULL;
|
||||
for (i = 0; i < process_num; i++) {
|
||||
current = &process[i];
|
||||
ogs_proc_terminate(current);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(OGS_TEST_INSIDE) && !defined(OGS_TEST_COMPILATION)
|
||||
#error "This header cannot be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef TEST_COMMON_APPLICATION_H
|
||||
#define TEST_COMMON_APPLICATION_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void test_epc_run(int argc, const char *const argv[],
|
||||
const char *name, void (*init)(const char * const argv[]));
|
||||
void test_5gc_run(int argc, const char *const argv[],
|
||||
const char *name, void (*init)(const char * const argv[]));
|
||||
void test_child_terminate(void);
|
||||
ogs_thread_t *test_child_create(const char *name, const char *const argv[]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TEST_COMMON_APPLICATION_H */
|
|
@ -0,0 +1,451 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "test-config-private.h"
|
||||
#include "test-common.h"
|
||||
|
||||
static test_context_t self;
|
||||
|
||||
static int context_initialized = 0;
|
||||
|
||||
void test_context_init(void)
|
||||
{
|
||||
ogs_assert(context_initialized == 0);
|
||||
|
||||
/* Initialize AMF context */
|
||||
memset(&self, 0, sizeof(test_context_t));
|
||||
|
||||
context_initialized = 1;
|
||||
}
|
||||
|
||||
void test_context_final(void)
|
||||
{
|
||||
ogs_assert(context_initialized == 1);
|
||||
|
||||
context_initialized = 0;
|
||||
}
|
||||
|
||||
test_context_t *test_self(void)
|
||||
{
|
||||
return &self;
|
||||
}
|
||||
|
||||
static int test_context_prepare(void)
|
||||
{
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
static int test_context_validation(void)
|
||||
{
|
||||
return OGS_OK;
|
||||
}
|
||||
|
||||
int test_context_parse_config(void)
|
||||
{
|
||||
int rv;
|
||||
yaml_document_t *document = NULL;
|
||||
ogs_yaml_iter_t root_iter;
|
||||
|
||||
document = ogs_config()->document;
|
||||
ogs_assert(document);
|
||||
|
||||
rv = test_context_prepare();
|
||||
if (rv != OGS_OK) return rv;
|
||||
|
||||
ogs_yaml_iter_init(&root_iter, document);
|
||||
while (ogs_yaml_iter_next(&root_iter)) {
|
||||
const char *root_key = ogs_yaml_iter_key(&root_iter);
|
||||
ogs_assert(root_key);
|
||||
if (!strcmp(root_key, "amf")) {
|
||||
ogs_yaml_iter_t amf_iter;
|
||||
ogs_yaml_iter_recurse(&root_iter, &amf_iter);
|
||||
while (ogs_yaml_iter_next(&amf_iter)) {
|
||||
const char *amf_key = ogs_yaml_iter_key(&amf_iter);
|
||||
ogs_assert(amf_key);
|
||||
if (!strcmp(amf_key, "guami")) {
|
||||
ogs_yaml_iter_t guami_array, guami_iter;
|
||||
ogs_yaml_iter_recurse(&amf_iter, &guami_array);
|
||||
do {
|
||||
const char *mcc = NULL, *mnc = NULL;
|
||||
const char *region = NULL, *set = NULL;
|
||||
const char *pointer = NULL;
|
||||
ogs_assert(self.num_of_served_guami <=
|
||||
MAX_NUM_OF_SERVED_GUAMI);
|
||||
|
||||
if (ogs_yaml_iter_type(&guami_array) ==
|
||||
YAML_MAPPING_NODE) {
|
||||
memcpy(&guami_iter, &guami_array,
|
||||
sizeof(ogs_yaml_iter_t));
|
||||
} else if (ogs_yaml_iter_type(&guami_array) ==
|
||||
YAML_SEQUENCE_NODE) {
|
||||
if (!ogs_yaml_iter_next(&guami_array))
|
||||
break;
|
||||
ogs_yaml_iter_recurse(&guami_array,
|
||||
&guami_iter);
|
||||
} else if (ogs_yaml_iter_type(&guami_array) ==
|
||||
YAML_SCALAR_NODE) {
|
||||
break;
|
||||
} else
|
||||
ogs_assert_if_reached();
|
||||
|
||||
while (ogs_yaml_iter_next(&guami_iter)) {
|
||||
const char *guami_key =
|
||||
ogs_yaml_iter_key(&guami_iter);
|
||||
ogs_assert(guami_key);
|
||||
if (!strcmp(guami_key, "plmn_id")) {
|
||||
ogs_yaml_iter_t plmn_id_iter;
|
||||
|
||||
ogs_yaml_iter_recurse(&guami_iter,
|
||||
&plmn_id_iter);
|
||||
while (ogs_yaml_iter_next(&plmn_id_iter)) {
|
||||
const char *plmn_id_key =
|
||||
ogs_yaml_iter_key(&plmn_id_iter);
|
||||
ogs_assert(plmn_id_key);
|
||||
if (!strcmp(plmn_id_key, "mcc")) {
|
||||
mcc = ogs_yaml_iter_value(
|
||||
&plmn_id_iter);
|
||||
} else if (!strcmp(plmn_id_key, "mnc")) {
|
||||
mnc = ogs_yaml_iter_value(
|
||||
&plmn_id_iter);
|
||||
}
|
||||
}
|
||||
|
||||
if (mcc && mnc) {
|
||||
ogs_plmn_id_build(
|
||||
&self.served_guami[
|
||||
self.num_of_served_guami].
|
||||
plmn_id,
|
||||
atoi(mcc), atoi(mnc), strlen(mnc));
|
||||
}
|
||||
} else if (!strcmp(guami_key, "amf_id")) {
|
||||
ogs_yaml_iter_t amf_id_iter;
|
||||
|
||||
ogs_yaml_iter_recurse(&guami_iter,
|
||||
&amf_id_iter);
|
||||
while (ogs_yaml_iter_next(&amf_id_iter)) {
|
||||
const char *amf_id_key =
|
||||
ogs_yaml_iter_key(&amf_id_iter);
|
||||
ogs_assert(amf_id_key);
|
||||
if (!strcmp(amf_id_key, "region")) {
|
||||
region = ogs_yaml_iter_value(
|
||||
&amf_id_iter);
|
||||
} else if (!strcmp(amf_id_key, "set")) {
|
||||
set = ogs_yaml_iter_value(
|
||||
&amf_id_iter);
|
||||
} else if (!strcmp(amf_id_key, "pointer")) {
|
||||
pointer = ogs_yaml_iter_value(
|
||||
&amf_id_iter);
|
||||
}
|
||||
}
|
||||
|
||||
if (region && set) {
|
||||
ogs_amf_id_build(
|
||||
&self.served_guami[
|
||||
self.num_of_served_guami].
|
||||
amf_id,
|
||||
atoi(region), atoi(set),
|
||||
pointer ? atoi(pointer) : 0);
|
||||
}
|
||||
} else
|
||||
ogs_warn("unknown key `%s`", guami_key);
|
||||
}
|
||||
|
||||
if (mnc && mcc && region && set) {
|
||||
self.num_of_served_guami++;
|
||||
} else {
|
||||
ogs_warn("Ignore guami : "
|
||||
"mcc(%s), mnc(%s), region(%s), set(%s)",
|
||||
mcc, mnc, region, set);
|
||||
}
|
||||
} while (ogs_yaml_iter_type(&guami_array) ==
|
||||
YAML_SEQUENCE_NODE);
|
||||
} else if (!strcmp(amf_key, "tai")) {
|
||||
int num_of_list0 = 0;
|
||||
ogs_5gs_tai0_list_t *list0 = NULL;
|
||||
ogs_5gs_tai2_list_t *list2 = NULL;
|
||||
|
||||
ogs_assert(self.num_of_served_tai <=
|
||||
OGS_MAX_NUM_OF_SERVED_TAI);
|
||||
list0 = &self.served_tai[self.num_of_served_tai].list0;
|
||||
ogs_assert(list0);
|
||||
list2 = &self.served_tai[self.num_of_served_tai].list2;
|
||||
ogs_assert(list2);
|
||||
|
||||
ogs_yaml_iter_t tai_array, tai_iter;
|
||||
ogs_yaml_iter_recurse(&amf_iter, &tai_array);
|
||||
do {
|
||||
const char *mcc = NULL, *mnc = NULL;
|
||||
ogs_uint24_t tac[OGS_MAX_NUM_OF_TAI];
|
||||
int num_of_tac = 0;
|
||||
|
||||
if (ogs_yaml_iter_type(&tai_array) ==
|
||||
YAML_MAPPING_NODE) {
|
||||
memcpy(&tai_iter, &tai_array,
|
||||
sizeof(ogs_yaml_iter_t));
|
||||
} else if (ogs_yaml_iter_type(&tai_array) ==
|
||||
YAML_SEQUENCE_NODE) {
|
||||
if (!ogs_yaml_iter_next(&tai_array))
|
||||
break;
|
||||
ogs_yaml_iter_recurse(&tai_array,
|
||||
&tai_iter);
|
||||
} else if (ogs_yaml_iter_type(&tai_array) ==
|
||||
YAML_SCALAR_NODE) {
|
||||
break;
|
||||
} else
|
||||
ogs_assert_if_reached();
|
||||
|
||||
while (ogs_yaml_iter_next(&tai_iter)) {
|
||||
const char *tai_key = ogs_yaml_iter_key(&tai_iter);
|
||||
ogs_assert(tai_key);
|
||||
if (!strcmp(tai_key, "plmn_id")) {
|
||||
ogs_yaml_iter_t plmn_id_iter;
|
||||
|
||||
ogs_yaml_iter_recurse(&tai_iter, &plmn_id_iter);
|
||||
while (ogs_yaml_iter_next(&plmn_id_iter)) {
|
||||
const char *plmn_id_key =
|
||||
ogs_yaml_iter_key(&plmn_id_iter);
|
||||
ogs_assert(plmn_id_key);
|
||||
if (!strcmp(plmn_id_key, "mcc")) {
|
||||
mcc = ogs_yaml_iter_value(
|
||||
&plmn_id_iter);
|
||||
} else if (!strcmp(plmn_id_key, "mnc")) {
|
||||
mnc = ogs_yaml_iter_value(
|
||||
&plmn_id_iter);
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(tai_key, "tac")) {
|
||||
ogs_yaml_iter_t tac_iter;
|
||||
ogs_yaml_iter_recurse(&tai_iter, &tac_iter);
|
||||
ogs_assert(ogs_yaml_iter_type(&tac_iter) !=
|
||||
YAML_MAPPING_NODE);
|
||||
|
||||
do {
|
||||
const char *v = NULL;
|
||||
|
||||
ogs_assert(num_of_tac <=
|
||||
OGS_MAX_NUM_OF_TAI);
|
||||
if (ogs_yaml_iter_type(&tac_iter) ==
|
||||
YAML_SEQUENCE_NODE) {
|
||||
if (!ogs_yaml_iter_next(&tac_iter))
|
||||
break;
|
||||
}
|
||||
|
||||
v = ogs_yaml_iter_value(&tac_iter);
|
||||
if (v) {
|
||||
tac[num_of_tac].v = atoi(v);
|
||||
num_of_tac++;
|
||||
}
|
||||
} while (
|
||||
ogs_yaml_iter_type(&tac_iter) ==
|
||||
YAML_SEQUENCE_NODE);
|
||||
} else
|
||||
ogs_warn("unknown key `%s`", tai_key);
|
||||
}
|
||||
|
||||
if (mcc && mnc && num_of_tac) {
|
||||
if (num_of_tac == 1) {
|
||||
ogs_plmn_id_build(
|
||||
&list2->tai[list2->num].plmn_id,
|
||||
atoi(mcc), atoi(mnc), strlen(mnc));
|
||||
list2->tai[list2->num].tac.v = tac[0].v;
|
||||
|
||||
list2->num++;
|
||||
if (list2->num > 1)
|
||||
list2->type = OGS_TAI2_TYPE;
|
||||
else
|
||||
list2->type = OGS_TAI1_TYPE;
|
||||
} else if (num_of_tac > 1) {
|
||||
int i;
|
||||
ogs_plmn_id_build(
|
||||
&list0->tai[num_of_list0].plmn_id,
|
||||
atoi(mcc), atoi(mnc), strlen(mnc));
|
||||
for (i = 0; i < num_of_tac; i++) {
|
||||
list0->tai[num_of_list0].tac[i].v =
|
||||
tac[i].v;
|
||||
}
|
||||
|
||||
list0->tai[num_of_list0].num = num_of_tac;
|
||||
list0->tai[num_of_list0].type = OGS_TAI0_TYPE;
|
||||
|
||||
num_of_list0++;
|
||||
}
|
||||
} else {
|
||||
ogs_warn("Ignore tai : mcc(%p), mnc(%p), "
|
||||
"num_of_tac(%d)", mcc, mnc, num_of_tac);
|
||||
}
|
||||
} while (ogs_yaml_iter_type(&tai_array) ==
|
||||
YAML_SEQUENCE_NODE);
|
||||
|
||||
if (list2->num || num_of_list0) {
|
||||
self.num_of_served_tai++;
|
||||
}
|
||||
} else if (!strcmp(amf_key, "plmn")) {
|
||||
ogs_yaml_iter_t plmn_array, plmn_iter;
|
||||
ogs_yaml_iter_recurse(&amf_iter, &plmn_array);
|
||||
do {
|
||||
const char *mnc = NULL, *mcc = NULL;
|
||||
ogs_assert(self.num_of_plmn_support <=
|
||||
OGS_MAX_NUM_OF_PLMN);
|
||||
|
||||
if (ogs_yaml_iter_type(&plmn_array) ==
|
||||
YAML_MAPPING_NODE) {
|
||||
memcpy(&plmn_iter, &plmn_array,
|
||||
sizeof(ogs_yaml_iter_t));
|
||||
} else if (ogs_yaml_iter_type(&plmn_array) ==
|
||||
YAML_SEQUENCE_NODE) {
|
||||
if (!ogs_yaml_iter_next(&plmn_array))
|
||||
break;
|
||||
ogs_yaml_iter_recurse(&plmn_array,
|
||||
&plmn_iter);
|
||||
} else if (ogs_yaml_iter_type(&plmn_array) ==
|
||||
YAML_SCALAR_NODE) {
|
||||
break;
|
||||
} else
|
||||
ogs_assert_if_reached();
|
||||
|
||||
while (ogs_yaml_iter_next(&plmn_iter)) {
|
||||
const char *plmn_key =
|
||||
ogs_yaml_iter_key(&plmn_iter);
|
||||
ogs_assert(plmn_key);
|
||||
if (!strcmp(plmn_key, "plmn_id")) {
|
||||
ogs_yaml_iter_t plmn_id_iter;
|
||||
|
||||
ogs_yaml_iter_recurse(&plmn_iter,
|
||||
&plmn_id_iter);
|
||||
while (ogs_yaml_iter_next(&plmn_id_iter)) {
|
||||
const char *plmn_id_key =
|
||||
ogs_yaml_iter_key(&plmn_id_iter);
|
||||
ogs_assert(plmn_id_key);
|
||||
if (!strcmp(plmn_id_key, "mcc")) {
|
||||
mcc = ogs_yaml_iter_value(
|
||||
&plmn_id_iter);
|
||||
} else if (!strcmp(plmn_id_key, "mnc")) {
|
||||
mnc = ogs_yaml_iter_value(
|
||||
&plmn_id_iter);
|
||||
}
|
||||
}
|
||||
|
||||
if (mcc && mnc) {
|
||||
ogs_plmn_id_build(
|
||||
&self.plmn_support[
|
||||
self.num_of_plmn_support].
|
||||
plmn_id,
|
||||
atoi(mcc), atoi(mnc), strlen(mnc));
|
||||
}
|
||||
} else if (!strcmp(plmn_key, "s_nssai")) {
|
||||
ogs_yaml_iter_t s_nssai_array, s_nssai_iter;
|
||||
ogs_yaml_iter_recurse(&plmn_iter,
|
||||
&s_nssai_array);
|
||||
do {
|
||||
ogs_s_nssai_t *s_nssai = NULL;
|
||||
const char *sst = NULL, *sd = NULL;
|
||||
ogs_assert(
|
||||
self.plmn_support[
|
||||
self.num_of_plmn_support].
|
||||
num_of_s_nssai <=
|
||||
OGS_MAX_NUM_OF_S_NSSAI);
|
||||
s_nssai = &self.plmn_support[
|
||||
self.num_of_plmn_support].s_nssai[
|
||||
self.plmn_support[
|
||||
self.num_of_plmn_support].
|
||||
num_of_s_nssai];
|
||||
ogs_assert(s_nssai);
|
||||
|
||||
if (ogs_yaml_iter_type(&s_nssai_array) ==
|
||||
YAML_MAPPING_NODE) {
|
||||
memcpy(&s_nssai_iter, &s_nssai_array,
|
||||
sizeof(ogs_yaml_iter_t));
|
||||
} else if (ogs_yaml_iter_type(
|
||||
&s_nssai_array) ==
|
||||
YAML_SEQUENCE_NODE) {
|
||||
if (!ogs_yaml_iter_next(&s_nssai_array))
|
||||
break;
|
||||
ogs_yaml_iter_recurse(&s_nssai_array,
|
||||
&s_nssai_iter);
|
||||
} else if (ogs_yaml_iter_type(
|
||||
&s_nssai_array) ==
|
||||
YAML_SCALAR_NODE) {
|
||||
break;
|
||||
} else
|
||||
ogs_assert_if_reached();
|
||||
|
||||
while (ogs_yaml_iter_next(&s_nssai_iter)) {
|
||||
const char *s_nssai_key =
|
||||
ogs_yaml_iter_key(&s_nssai_iter);
|
||||
ogs_assert(s_nssai_key);
|
||||
if (!strcmp(s_nssai_key, "sst")) {
|
||||
sst = ogs_yaml_iter_value(
|
||||
&s_nssai_iter);
|
||||
} else if (!strcmp(
|
||||
s_nssai_key, "sd")) {
|
||||
sd = ogs_yaml_iter_value(
|
||||
&s_nssai_iter);
|
||||
}
|
||||
}
|
||||
|
||||
if (sst) {
|
||||
s_nssai->sst = atoi(sst);
|
||||
if (sd) {
|
||||
s_nssai->sd =
|
||||
ogs_uint24_from_string(
|
||||
(char*)sd);
|
||||
} else {
|
||||
s_nssai->sd.v =
|
||||
OGS_S_NSSAI_NO_SD_VALUE;
|
||||
}
|
||||
|
||||
self.plmn_support[
|
||||
self.num_of_plmn_support].
|
||||
num_of_s_nssai++;
|
||||
}
|
||||
|
||||
} while (ogs_yaml_iter_type(&s_nssai_array) ==
|
||||
YAML_SEQUENCE_NODE);
|
||||
} else
|
||||
ogs_warn("unknown key `%s`", plmn_key);
|
||||
}
|
||||
|
||||
if (self.plmn_support[
|
||||
self.num_of_plmn_support].num_of_s_nssai &&
|
||||
mcc && mnc) {
|
||||
self.num_of_plmn_support++;
|
||||
} else {
|
||||
ogs_warn("Ignore plmn : "
|
||||
"s_nssai(%d) mcc(%s), mnc(%s)",
|
||||
self.plmn_support[
|
||||
self.num_of_plmn_support].num_of_s_nssai,
|
||||
mcc, mnc);
|
||||
self.plmn_support[
|
||||
self.num_of_plmn_support].num_of_s_nssai = 0;
|
||||
}
|
||||
} while (ogs_yaml_iter_type(&plmn_array) ==
|
||||
YAML_SEQUENCE_NODE);
|
||||
} else if (!strcmp(amf_key, "sbi")) {
|
||||
/* handle config in sbi library */
|
||||
} else
|
||||
ogs_warn("unknown key `%s`", amf_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rv = test_context_validation();
|
||||
if (rv != OGS_OK) return rv;
|
||||
|
||||
return OGS_OK;
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(OGS_TEST_INSIDE) && !defined(OGS_TEST_COMPILATION)
|
||||
#error "This header cannot be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef TEST_COMMON_CONTEXT_H
|
||||
#define TEST_COMMON_CONTEXT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MAX_NUM_OF_SERVED_GUAMI 8
|
||||
|
||||
typedef struct test_context_s {
|
||||
/* Served GUMME */
|
||||
uint8_t num_of_served_guami;
|
||||
struct {
|
||||
ogs_plmn_id_t plmn_id;
|
||||
ogs_amf_id_t amf_id;
|
||||
} served_guami[MAX_NUM_OF_SERVED_GUAMI];
|
||||
|
||||
/* Served TAI */
|
||||
uint8_t num_of_served_tai;
|
||||
struct {
|
||||
ogs_5gs_tai0_list_t list0;
|
||||
ogs_5gs_tai2_list_t list2;
|
||||
} served_tai[OGS_MAX_NUM_OF_SERVED_TAI];
|
||||
|
||||
/* PLMN Support */
|
||||
uint8_t num_of_plmn_support;
|
||||
struct {
|
||||
ogs_plmn_id_t plmn_id;
|
||||
int num_of_s_nssai;
|
||||
ogs_s_nssai_t s_nssai[OGS_MAX_NUM_OF_S_NSSAI];
|
||||
} plmn_support[OGS_MAX_NUM_OF_PLMN];
|
||||
|
||||
} test_context_t;
|
||||
|
||||
void test_context_init(void);
|
||||
void test_context_final(void);
|
||||
test_context_t *test_self(void);
|
||||
|
||||
int test_context_parse_config(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TEST_COMMON_CONTEXT_H */
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "test-common.h"
|
||||
|
||||
ogs_socknode_t *test_gtpu_server(const char *ipstr, int port)
|
||||
{
|
||||
int rv;
|
||||
ogs_sockaddr_t *addr = NULL;
|
||||
ogs_socknode_t *node = NULL;
|
||||
ogs_sock_t *sock = NULL;
|
||||
|
||||
rv = ogs_getaddrinfo(&addr, AF_UNSPEC, ipstr, port, 0);
|
||||
ogs_assert(rv == OGS_OK);
|
||||
|
||||
node = ogs_socknode_new(addr);
|
||||
ogs_assert(node);
|
||||
|
||||
sock = ogs_udp_server(node);
|
||||
ogs_assert(sock);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
ogs_pkbuf_t *test_gtpu_read(ogs_socknode_t *node)
|
||||
{
|
||||
int rc = 0;
|
||||
ogs_pkbuf_t *recvbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
|
||||
ogs_pkbuf_put(recvbuf, OGS_MAX_SDU_LEN);
|
||||
|
||||
ogs_assert(node);
|
||||
ogs_assert(node->sock);
|
||||
|
||||
while (1) {
|
||||
rc = ogs_recv(node->sock->fd, recvbuf->data, recvbuf->len, 0);
|
||||
if (rc <= 0) {
|
||||
if (errno == EAGAIN) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
recvbuf->len = rc;
|
||||
|
||||
return recvbuf;
|
||||
}
|
||||
|
||||
void test_gtpu_close(ogs_socknode_t *node)
|
||||
{
|
||||
ogs_socknode_free(node);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
*
|
||||
* This file is part of Open5GS.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TEST_COMMON_GTPU_H
|
||||
#define TEST_COMMON_GTPU_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
ogs_socknode_t *test_gtpu_server(const char *ipstr, int port);
|
||||
ogs_pkbuf_t *test_gtpu_read(ogs_socknode_t *node);
|
||||
void test_gtpu_close(ogs_socknode_t *node);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TEST_COMMON_GTPU_H */
|
|
@ -0,0 +1,58 @@
|
|||
# Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
|
||||
|
||||
# This file is part of Open5GS.
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
libtestcommon_conf = configuration_data()
|
||||
libtestcommon_conf.set_quoted('MESON_BUILD_ROOT', meson.build_root())
|
||||
configure_file(output : 'test-config-private.h',
|
||||
configuration : libtestcommon_conf)
|
||||
|
||||
libtestcommon_sources = files('''
|
||||
sctp.c
|
||||
gtpu.c
|
||||
context.c
|
||||
application.c
|
||||
|
||||
ngap-build.c
|
||||
'''.split())
|
||||
|
||||
libtestcommon_inc = include_directories('.')
|
||||
|
||||
libtestcommon = static_library('testcomon',
|
||||
sources : libtestcommon_sources,
|
||||
c_args : testcore_cc_flags,
|
||||
include_directories : [libtestcommon_inc, testinc],
|
||||
dependencies : [libcore_dep,
|
||||
libapp_dep,
|
||||
libdbi_dep,
|
||||
libsctp_dep,
|
||||
libngap_dep,
|
||||
libnas_eps_dep,
|
||||
libnas_5gs_dep,
|
||||
libdiameter_common_dep],
|
||||
install : false)
|
||||
|
||||
libtestcommon_dep = declare_dependency(
|
||||
link_with : libtestcommon,
|
||||
include_directories : [libtestcommon_inc, testinc],
|
||||
dependencies : [libcore_dep,
|
||||
libapp_dep,
|
||||
libdbi_dep,
|
||||
libsctp_dep,
|
||||
libngap_dep,
|
||||
libnas_eps_dep,
|
||||
libnas_5gs_dep,
|
||||
libdiameter_common_dep])
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue