Compare commits

...

14 Commits

Author SHA1 Message Date
Sukchan Lee 390a9dd637 [MME] incorrect behavior of the SGsAP
1. According to ETSI TS 129 118 4.1, if the Network Access Mode (NAM) is set
   to "Packet only," no SGs association should be established.

2. If the NAM is set to "Packet and Circuit," and the SGs association is
   rejected by the CS core, this rejection should only impact
   the SGs association itself and not result in a UE attach rejection
   for a UE with a valid HSS account.
2024-03-24 20:31:56 +09:00
Sukchan Lee 7c14073533 [UDM] Added validation for pubkey
a cryptographic vulnerability in the SUCI decryption routines
of Open5GS 5G—specifically Profile B, which uses P-256 (secp256r1)
for its elliptic curve routines.

If a mobile device user passes a public key within its SUCI
that does not correspond to a valid point on the P-256 elliptic curve,
the Open5GS UDM will not check the point
before running elliptic curve operations with it and returning a response
to the mobile device user.

If the public key is not checked to be a valid point, an attacker can leverage
this behavior to extract the Profile B private key from the UDM,
as has been done in other domains
(https://owasp.org/www-pdf-archive/Practical_Invalid_Curve_Attacks_on_TLS-ECDH_-_Juraj_Somorovsky.pdf).

Note that Profile A is not similarly vulnerable to this, as it is impossible
to construct an invalid point on a curve25519 elliptic curve.

There was some work that went into developing a practical proof of concept
of this kind of attack against free5gc last year; it can be found here:

https://www.gsma.com/security/wp-content/uploads/2023/10/0073-invalid_curve.pdf

And here is the free5gc security advisory:

https://github.com/advisories/GHSA-cqvv-r3g3-26rf

To mitigate this issue in Open5GS, the public key of the UE must be validated
by the UDM prior to use. Adding a validation function such as the following
should work:

I designed this code based on information from https://crypto.stackexchange.com/questions/90151/verify-that-a-point-belongs-to-secp256r1.
2024-03-24 14:09:10 +09:00
Sukchan Lee cf4ad1f248 [PFCP] Session removal while waiting PFCP reply (#3040)
'node_timeout' and some other functions can remove a smf_sess_t
while that session is still waiting for a PFCP reply
and has an active PFCP xact.

In this case, xact->data points to the deleted session
and xact's timeout function (sess_5gc_timeout for example)
eventually refers to this already freed session.

This fix prevents duplicate deletes from occurring by checking to see
if the session context has already been deleted when the timeout occurs.

Additionally, it moves session deletions out of timer callbacks into
state machine by reselect_upf().

Due to the way 'ogs_timer_mgr_expire' calls timer callbacks,
one must not stop or expire timers from within a timer callback.

And now one must not remove sessions from within a timer callback.
2024-03-24 09:50:23 +09:00
Sukchan Lee a667525041 [GTP/PFCP]] incorrect dst TEI=0/SEID=0 (#3043)
If eg. PCRF or AAA diameter link is not yet ready (eg. PCRF crashed), and
a client sends a CreateSessionRequest announcing its ow F-TEID,
then open5gs-smfd answers with Create Session Response Cause=
"Remote peer not responding", but it is not setting the received F-TEID
in the header of the response, instead it sends with TEI=0.

As a result, the peer cannot match the CreateSessionResponse, and needs
to rely on its own timeout timer to figure out that specific request failed.

This also happens in PFCP, so to solve this problem, I added teid/seid_presence
to the interface that sends the error message as shown below.

void ogs_gtp2_send_error_message(ogs_gtp_xact_t *xact,
        int teid_presence, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_pfcp_send_error_message(
    ogs_pfcp_xact_t *xact, int seid_presence, uint64_t seid, uint8_t type,
    uint8_t cause_value, uint16_t offending_ie_value);
2024-03-23 10:06:16 +09:00
Sukchan Lee 1dc4300203 [AMF] ran_ue can be NULL in IMPLICIT Dereg (#2999)
When we try to send an SBI message to SMF to release a session,
sometimes ran_ue is NULL. This happens when the Mobile Reachable Timer expires
and Implicit Deregistration is triggered.

To account for this case, we added the `ran_ue` parameter to the SBI interface
and made it work even if it is NULL.
2024-03-22 06:51:09 +09:00
Pau Espin 3b5e851f5d [SMF] Gy: Remove 3GPP-RAT-Type AVP from Multiple-Services-Credit-Control AVP
This AVP is optional and was added in later releases of the 3GPP TS
32.299 spec. For instance, it shows up in Release 16 (V16.2.0), but
doesn't show up in Release 12 (V12.7.0).

Some OCS, like PortaOne OCS, implement older versions of the release
(V12.14.0), and hence fail when receiving the 3GPP-RAT-Type inside
Multiple-Services-Credit-Control AVP.
Since nowadays we also send the 3GPP-RAT-Type in PS-Information AVP,
which has been specified for longer time (it already shows up in
V12.7.0), drop it from Multiple-Services-Credit-Control to have greater
compatibility with other vendors.
2024-03-21 07:14:06 +09:00
Pau Espin d0b31177cc [SMF] Gy: Include 3GPP-RAT-Type AVP in PS-Information AVP
The AVP is optional, but used by some OCS vendors like PortaOne OCS make
use of it.
2024-03-21 07:14:06 +09:00
Pau Espin 6420e80fe6 [SMF] Gy: Split PS-Information AVP creation into its own function
Makes the already long function easier to follow, since there's one
level less of encapsulation inside it.
2024-03-21 07:14:06 +09:00
Pau Espin ca5a29dbe3 [SMF] Gy: Use correct QoS AVP descriptor from Gy instead of Gx one 2024-03-21 07:13:55 +09:00
Pau Espin 12158eebb8 [SMF] Gy: Check Multiple-Services-Credit-Control Result-Code 2024-03-21 07:13:44 +09:00
Matej Gradišar e1820e4e54
UE context transfer (#3052)
* [SBI] Handle and store AMF info

* [SBI] Add "target GUAMI" discovery option

* [SBI] Handle UeContextTransfer request and response messages

* [AMF] Handle NF discovery from AMF to AMF

* [AMF] Add UE Context Transfer Request/Response from AMF to AMF

* [SCP] Handle UeContextTransfer

* Follow-up on #3052

* [AMF] force authentication after 'Ue context transfer' for now

* [AMF] force authentication after 'Ue context transfer' for now

---------

Co-authored-by: Sukchan Lee <acetcom@gmail.com>
2024-03-21 07:07:25 +09:00
Pau Espin ea122da9fc [SMF] Allow Gy CCA event to contain NULL gtp_xact
This happens for instance when the session is terminated due to a
rejection coming from the OCS, hence no originating GTP xact producing
the tear down.
2024-03-20 07:03:18 +09:00
Pau Espin 32a275b9a8 [SMF] smf_gy_send_ccr: Allow NULL xact
The xact may well be NULL, eg. when tearin down the session
(send_ccr_termination_req_gx_gy_s6b()) because OCS rejected an update:
Hence there's no GTP xact originating the tear down, aka e->gtp-xact
passed to the function is NULL.

smf_gx_send_ccr() is already handling this case properly, contrary to smf_gf_send_ccr().
2024-03-20 07:03:18 +09:00
Pau Espin 10a0647f09 [SMF] Gy: Tear down session when CCR-Update is rejected by OCS 2024-03-20 07:03:18 +09:00
80 changed files with 2165 additions and 408 deletions

View File

@ -334,7 +334,7 @@ Change back to the srsRAN source directory and copy the main config example as w
```bash
$ cp srsenb/enb.conf.example srsenb/enb.conf
$ cp srsenb/rr.conf.example srsenb/rr.conf
$ cp srsenb/drb.conf.example srsenb/drb.conf
$ cp srsenb/rb.conf.example srsenb/rb.conf
$ cp srsenb/sib.conf.example srsenb/sib.conf
```

View File

@ -199,6 +199,8 @@ void ogs_timer_mgr_expire(ogs_timer_mgr_t *manager)
ogs_list_add(&list, &this->lnode);
}
/* You should not perform a delete on a timer using ogs_timer_delete()
* in a callback function this->cb(). */
ogs_list_for_each(&list, lnode) {
this = ogs_rb_entry(lnode, ogs_timer_t, lnode);
ogs_timer_stop(this);

View File

@ -4,6 +4,8 @@
#include <string.h>
#include "ogs-core.h"
#define NUM_ECC_DIGITS (ECC_BYTES/8)
#define MAX_TRIES 16
@ -82,6 +84,7 @@ static int getRandomNumber(uint64_t *p_vli)
HCRYPTPROV l_prov;
if(!CryptAcquireContext(&l_prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
ogs_error("CryptAcquireContext() failed");
return 0;
}
@ -107,9 +110,11 @@ static int getRandomNumber(uint64_t *p_vli)
int l_fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
if(l_fd == -1)
{
ogs_error("open(/dev/urandom) failed");
l_fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
if(l_fd == -1)
{
ogs_error("open(/dev/random) failed");
return 0;
}
}
@ -122,6 +127,7 @@ static int getRandomNumber(uint64_t *p_vli)
if(l_read <= 0)
{ // read failed
close(l_fd);
ogs_error("read() failed");
return 0;
}
l_left -= l_read;
@ -1073,6 +1079,7 @@ int ecc_make_key(uint8_t p_publicKey[ECC_BYTES+1], uint8_t p_privateKey[ECC_BYTE
{
if(!getRandomNumber(l_private) || (l_tries++ >= MAX_TRIES))
{
ogs_error("getRandomNumber() failed [%d]", l_tries);
return 0;
}
if(vli_isZero(l_private))
@ -1096,6 +1103,45 @@ int ecc_make_key(uint8_t p_publicKey[ECC_BYTES+1], uint8_t p_privateKey[ECC_BYTE
return 1;
}
#define CURVE_A_32 {0xFFFFFFFFFFFFFFFCull, 0x00000000FFFFFFFFull, 0x0000000000000000ull, 0xFFFFFFFF00000001ull}
static int ecdh_validate_pubkey(EccPoint l_public, uint64_t l_private[NUM_ECC_DIGITS]) {
uint64_t left[NUM_ECC_DIGITS];
uint64_t right[NUM_ECC_DIGITS];
uint64_t curve_a[NUM_ECC_DIGITS] = CURVE_A_32;
/*
* To ensure l_public is a valid point on the curve, we need to check:
* y^2 % p == (x^3 + a * x + b) % p)
*/
/* Compute y^2 % p and store in `left` */
vli_modSquare_fast(left, l_public.y);
/* Compute x^3 and store in `right` */
vli_modSquare_fast(right, l_public.x);
vli_modMult_fast(right, right, l_public.x);
/* Compute a * x and store in `curve_a` */
vli_modMult_fast(curve_a, curve_a, l_public.x);
/* Store ((a * x) + b) % p in `curve_a */
vli_modAdd(curve_a, curve_a, curve_b, curve_p);
/*
* Combine x^3 and ((a * x) + b) to make (x^3 + a * x + b) % p);
* store in `right`
*/
vli_modAdd(right, right, curve_a, curve_p);
int i;
for (i = 0; i < NUM_ECC_DIGITS; i++) {
if (left[i] != right[i]) {
return 0; // y^2 % p != (x^3 + a * x + b) % p)
}
}
return 1;
}
int ecdh_shared_secret(const uint8_t p_publicKey[ECC_BYTES+1], const uint8_t p_privateKey[ECC_BYTES], uint8_t p_secret[ECC_BYTES])
{
EccPoint l_public;
@ -1104,12 +1150,23 @@ int ecdh_shared_secret(const uint8_t p_publicKey[ECC_BYTES+1], const uint8_t p_p
if(!getRandomNumber(l_random))
{
ogs_error("getRandomNumber() failed");
return 0;
}
ecc_point_decompress(&l_public, p_publicKey);
ecc_bytes2native(l_private, p_privateKey);
/*
* Validate received public key `p_publicKey` is a valid point
* on curve P-256
*/
if (!ecdh_validate_pubkey(l_public, l_private))
{
ogs_error("ecdh_validate_pubkey() failed");
return 0;
}
EccPoint l_product;
EccPoint_mult(&l_product, &l_public, l_private, l_random);
@ -1202,6 +1259,7 @@ int ecdsa_sign(const uint8_t p_privateKey[ECC_BYTES], const uint8_t p_hash[ECC_B
{
if(!getRandomNumber(k) || (l_tries++ >= MAX_TRIES))
{
ogs_error("getRandomNumber() failed [%d]", l_tries);
return 0;
}
if(vli_isZero(k))
@ -1256,11 +1314,13 @@ int ecdsa_verify(const uint8_t p_publicKey[ECC_BYTES+1], const uint8_t p_hash[EC
if(vli_isZero(l_r) || vli_isZero(l_s))
{ /* r, s must not be 0. */
ogs_error("r, s must not be 0");
return 0;
}
if(vli_cmp(curve_n, l_r) != 1 || vli_cmp(curve_n, l_s) != 1)
{ /* r, s must be < n. */
ogs_error("r, s must be < n");
return 0;
}

View File

@ -187,6 +187,8 @@ typedef struct ogs_diam_gy_message_s {
uint32_t time_threshold;
uint32_t volume_threshold;
ogs_diam_gy_service_unit_t granted;
uint32_t result_code;
uint32_t *err;
} cca;
};
} ogs_diam_gy_message_t;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -128,16 +128,3 @@ int ogs_gtp_sendto(ogs_gtp_node_t *gnode, ogs_pkbuf_t *pkbuf)
return OGS_OK;
}
void ogs_gtp_send_error_message(
ogs_gtp_xact_t *xact, uint32_t teid, uint8_t type, uint8_t cause_value)
{
switch (xact->gtp_version) {
case 1:
ogs_gtp1_send_error_message(xact, teid, type, cause_value);
break;
case 2:
ogs_gtp2_send_error_message(xact, teid, type, cause_value);
break;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -72,9 +72,6 @@ int ogs_gtp_connect(ogs_sock_t *ipv4, ogs_sock_t *ipv6, ogs_gtp_node_t *gnode);
int ogs_gtp_send(ogs_gtp_node_t *gnode, ogs_pkbuf_t *pkbuf);
int ogs_gtp_sendto(ogs_gtp_node_t *gnode, ogs_pkbuf_t *pkbuf);
void ogs_gtp_send_error_message(
ogs_gtp_xact_t *xact, uint32_t teid, uint8_t type, uint8_t cause_value);
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by gtp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2023-08-26 16:35:12.648272 by acetcom
* Created on: 2024-03-23 07:21:22.444548 by acetcom
* from 29274-h70.docx
******************************************************************************/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by gtp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2023-08-26 16:35:12.642445 by acetcom
* Created on: 2024-03-23 07:21:22.438775 by acetcom
* from 29274-h70.docx
******************************************************************************/
@ -44,6 +44,9 @@ typedef struct ogs_gtp2_header_s {
struct {
#define OGS_GTP2_VERSION_0 0
#define OGS_GTP2_VERSION_1 1
#define OGS_GTP2_TEID_NO_PRESENCE 0
#define OGS_GTP2_TEID_PRESENCE 1
ED4(uint8_t version:3;,
uint8_t piggybacked:1;,
uint8_t teid_presence:1;,

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -160,8 +160,8 @@ ogs_pkbuf_t *ogs_gtp2_handle_echo_req(ogs_pkbuf_t *pkb)
return pkb_resp;
}
void ogs_gtp2_send_error_message(
ogs_gtp_xact_t *xact, uint32_t teid, uint8_t type, uint8_t cause_value)
void ogs_gtp2_send_error_message(ogs_gtp_xact_t *xact,
int teid_presence, uint32_t teid, uint8_t type, uint8_t cause_value)
{
int rv;
ogs_gtp2_message_t errmsg;
@ -170,6 +170,7 @@ void ogs_gtp2_send_error_message(
ogs_pkbuf_t *pkbuf = NULL;
memset(&errmsg, 0, sizeof(ogs_gtp2_message_t));
errmsg.h.teid_presence = teid_presence;
errmsg.h.teid = teid;
errmsg.h.type = type;
@ -257,7 +258,7 @@ void ogs_gtp2_send_echo_request(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_ECHO_REQUEST_TYPE;
h.teid = 0;
h.teid_presence = OGS_GTP2_TEID_NO_PRESENCE;
pkbuf = ogs_gtp2_build_echo_request(h.type, recovery, features);
if (!pkbuf) {
@ -284,7 +285,7 @@ void ogs_gtp2_send_echo_response(ogs_gtp_xact_t *xact,
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_ECHO_RESPONSE_TYPE;
h.teid = 0;
h.teid_presence = OGS_GTP2_TEID_NO_PRESENCE;
pkbuf = ogs_gtp2_build_echo_response(h.type, recovery, features);
if (!pkbuf) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -36,8 +36,8 @@ int ogs_gtp2_send_user_plane(
ogs_pkbuf_t *pkbuf);
ogs_pkbuf_t *ogs_gtp2_handle_echo_req(ogs_pkbuf_t *pkb);
void ogs_gtp2_send_error_message(
ogs_gtp_xact_t *xact, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_gtp2_send_error_message(ogs_gtp_xact_t *xact,
int teid_presence, uint32_t teid, uint8_t type, uint8_t cause_value);
void ogs_gtp2_send_echo_request(
ogs_gtp_node_t *gnode, uint8_t recovery, uint8_t features);

View File

@ -1,4 +1,4 @@
# Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
# Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
# This file is part of Open5GS.
@ -60,7 +60,7 @@ def write_file(f, string):
def output_header_to_file(f):
now = datetime.datetime.now()
f.write("""/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -461,6 +461,9 @@ typedef struct ogs_gtp2_header_s {
struct {
#define OGS_GTP2_VERSION_0 0
#define OGS_GTP2_VERSION_1 1
#define OGS_GTP2_TEID_NO_PRESENCE 0
#define OGS_GTP2_TEID_PRESENCE 1
ED4(uint8_t version:3;,
uint8_t piggybacked:1;,
uint8_t teid_presence:1;,

View File

@ -1,6 +1,7 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Copyright (C) 2023-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -407,7 +408,7 @@ int ogs_gtp_xact_update_tx(ogs_gtp_xact_t *xact,
return OGS_ERROR;
}
if (hdesc->type > OGS_GTP2_VERSION_NOT_SUPPORTED_INDICATION_TYPE) {
if (hdesc->teid_presence) {
gtp_hlen = OGS_GTPV2C_HEADER_LEN;
} else {
gtp_hlen = OGS_GTPV2C_HEADER_LEN - OGS_GTP2_TEID_LEN;
@ -420,12 +421,12 @@ int ogs_gtp_xact_update_tx(ogs_gtp_xact_t *xact,
h->version = 2;
h->type = hdesc->type;
if (hdesc->type > OGS_GTP2_VERSION_NOT_SUPPORTED_INDICATION_TYPE) {
h->teid_presence = 1;
if (hdesc->teid_presence) {
h->teid_presence = OGS_GTP2_TEID_PRESENCE;
h->teid = htobe32(hdesc->teid);
h->sqn = OGS_GTP2_XID_TO_SQN(xact->xid);
} else {
h->teid_presence = 0;
h->teid_presence = OGS_GTP2_TEID_NO_PRESENCE;
h->sqn_only = OGS_GTP2_XID_TO_SQN(xact->xid);
}
h->length = htobe16(pkbuf->len - 4);

View File

@ -968,3 +968,21 @@ int ogs_nas_parse_qos_rules(
return (int)(rule-first);
}
bool ogs_nas_5gs_guti_is_valid(ogs_nas_5gs_guti_t *guti)
{
if ((guti->amf_id.region !=0) &&
(guti->amf_id.set2 !=0) &&
(guti->m_tmsi != 0) &&
((guti->nas_plmn_id.mcc1) !=0 ||
(guti->nas_plmn_id.mcc2) !=0 ||
(guti->nas_plmn_id.mcc3) !=0) &&
((guti->nas_plmn_id.mnc1) !=0 ||
(guti->nas_plmn_id.mnc2) !=0 ||
(guti->nas_plmn_id.mnc3) !=0)) {
return true;
}
return false;
}

View File

@ -1192,6 +1192,8 @@ typedef struct ogs_nas_rsn_s {
uint8_t value;
} __attribute__ ((packed)) ogs_nas_rsn_t;
bool ogs_nas_5gs_guti_is_valid(ogs_nas_5gs_guti_t *guti);
#ifdef __cplusplus
}
#endif

View File

@ -870,6 +870,11 @@ ogs_pfcp_node_t *ogs_pfcp_node_new(ogs_sockaddr_t *sa_list)
return node;
}
ogs_pfcp_node_t *ogs_pfcp_node_cycle(ogs_pfcp_node_t *node)
{
return ogs_pool_cycle(&ogs_pfcp_node_pool, node);
}
void ogs_pfcp_node_free(ogs_pfcp_node_t *node)
{
ogs_assert(node);

View File

@ -393,6 +393,7 @@ ogs_pfcp_context_t *ogs_pfcp_self(void);
int ogs_pfcp_context_parse_config(const char *local, const char *remote);
ogs_pfcp_node_t *ogs_pfcp_node_new(ogs_sockaddr_t *sa_list);
ogs_pfcp_node_t *ogs_pfcp_node_cycle(ogs_pfcp_node_t *node);
void ogs_pfcp_node_free(ogs_pfcp_node_t *node);
ogs_pfcp_node_t *ogs_pfcp_node_add(

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by pfcp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2024-01-19 23:36:01.346970 by acetcom
* Created on: 2024-03-23 07:20:44.691773 by acetcom
* from 29244-h71-modified.docx
******************************************************************************/

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by pfcp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2024-01-19 23:36:01.327925 by acetcom
* Created on: 2024-03-23 07:20:44.672650 by acetcom
* from 29244-h71-modified.docx
******************************************************************************/
@ -41,6 +41,8 @@ extern "C" {
typedef struct ogs_pfcp_header_s {
union {
struct {
#define OGS_PFCP_SEID_NO_PRESENCE 0
#define OGS_PFCP_SEID_PRESENCE 1
ED4(uint8_t version:3;,
uint8_t spare1:3;,
uint8_t mp:1;,

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -140,7 +140,7 @@ int ogs_pfcp_send_heartbeat_request(ogs_pfcp_node_t *node,
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_HEARTBEAT_REQUEST_TYPE;
h.seid = 0;
h.seid_presence = OGS_PFCP_SEID_NO_PRESENCE;
xact = ogs_pfcp_xact_local_create(node, cb, node);
if (!xact) {
@ -176,7 +176,7 @@ int ogs_pfcp_send_heartbeat_response(ogs_pfcp_xact_t *xact)
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_HEARTBEAT_RESPONSE_TYPE;
h.seid = 0;
h.seid_presence = OGS_PFCP_SEID_NO_PRESENCE;
pkbuf = ogs_pfcp_build_heartbeat_response(h.type);
if (!pkbuf) {
@ -217,7 +217,7 @@ int ogs_pfcp_cp_send_association_setup_request(ogs_pfcp_node_t *node,
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE;
h.seid = 0;
h.seid_presence = OGS_PFCP_SEID_NO_PRESENCE;
xact = ogs_pfcp_xact_local_create(node, cb, node);
if (!xact) {
@ -254,7 +254,7 @@ int ogs_pfcp_cp_send_association_setup_response(ogs_pfcp_xact_t *xact,
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE;
h.seid = 0;
h.seid_presence = OGS_PFCP_SEID_NO_PRESENCE;
pkbuf = ogs_pfcp_cp_build_association_setup_response(h.type, cause);
if (!pkbuf) {
@ -286,7 +286,7 @@ int ogs_pfcp_up_send_association_setup_request(ogs_pfcp_node_t *node,
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_ASSOCIATION_SETUP_REQUEST_TYPE;
h.seid = 0;
h.seid_presence = OGS_PFCP_SEID_NO_PRESENCE;
xact = ogs_pfcp_xact_local_create(node, cb, node);
if (!xact) {
@ -323,7 +323,7 @@ int ogs_pfcp_up_send_association_setup_response(ogs_pfcp_xact_t *xact,
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_ASSOCIATION_SETUP_RESPONSE_TYPE;
h.seid = 0;
h.seid_presence = OGS_PFCP_SEID_NO_PRESENCE;
pkbuf = ogs_pfcp_up_build_association_setup_response(h.type, cause);
if (!pkbuf) {
@ -468,7 +468,7 @@ void ogs_pfcp_send_buffered_packet(ogs_pfcp_pdr_t *pdr)
}
void ogs_pfcp_send_error_message(
ogs_pfcp_xact_t *xact, uint64_t seid, uint8_t type,
ogs_pfcp_xact_t *xact, int seid_presence, uint64_t seid, uint8_t type,
uint8_t cause_value, uint16_t offending_ie_value)
{
int rv;
@ -480,6 +480,7 @@ void ogs_pfcp_send_error_message(
ogs_assert(xact);
memset(&errmsg, 0, sizeof(ogs_pfcp_message_t));
errmsg.h.seid_presence = seid_presence;
errmsg.h.seid = seid;
errmsg.h.type = type;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -86,7 +86,7 @@ int ogs_pfcp_send_end_marker(ogs_pfcp_pdr_t *pdr);
void ogs_pfcp_send_buffered_packet(ogs_pfcp_pdr_t *pdr);
void ogs_pfcp_send_error_message(
ogs_pfcp_xact_t *xact, uint64_t seid, uint8_t type,
ogs_pfcp_xact_t *xact, int seid_presence, uint64_t seid, uint8_t type,
uint8_t cause_value, uint16_t offending_ie_value);
#ifdef __cplusplus

View File

@ -1,4 +1,4 @@
# Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
# Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
# This file is part of Open5GS.
@ -54,7 +54,7 @@ def write_file(f, string):
def output_header_to_file(f):
now = datetime.datetime.now()
f.write("""/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -541,6 +541,8 @@ extern "C" {
typedef struct ogs_pfcp_header_s {
union {
struct {
#define OGS_PFCP_SEID_NO_PRESENCE 0
#define OGS_PFCP_SEID_PRESENCE 1
ED4(uint8_t version:3;,
uint8_t spare1:3;,
uint8_t mp:1;,

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -161,11 +161,6 @@ static ogs_pfcp_xact_t *ogs_pfcp_xact_remote_create(
return xact;
}
ogs_pfcp_xact_t *ogs_pfcp_xact_cycle(ogs_pfcp_xact_t *xact)
{
return ogs_pool_cycle(&pool, xact);
}
void ogs_pfcp_xact_delete_all(ogs_pfcp_node_t *node)
{
ogs_pfcp_xact_t *xact = NULL, *next_xact = NULL;
@ -251,7 +246,7 @@ int ogs_pfcp_xact_update_tx(ogs_pfcp_xact_t *xact,
return OGS_ERROR;
}
if (hdesc->type >= OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE) {
if (hdesc->seid_presence) {
pfcp_hlen = OGS_PFCP_HEADER_LEN;
} else {
pfcp_hlen = OGS_PFCP_HEADER_LEN - OGS_PFCP_SEID_LEN;
@ -264,7 +259,7 @@ int ogs_pfcp_xact_update_tx(ogs_pfcp_xact_t *xact,
h->version = OGS_PFCP_VERSION;
h->type = hdesc->type;
if (h->type >= OGS_PFCP_SESSION_ESTABLISHMENT_REQUEST_TYPE) {
if (hdesc->seid_presence) {
h->seid_presence = 1;
h->seid = htobe64(hdesc->seid);
h->sqn = OGS_PFCP_XID_TO_SQN(xact->xid);

View File

@ -133,7 +133,6 @@ void ogs_pfcp_xact_final(void);
ogs_pfcp_xact_t *ogs_pfcp_xact_local_create(ogs_pfcp_node_t *node,
void (*cb)(ogs_pfcp_xact_t *xact, void *data), void *data);
ogs_pfcp_xact_t *ogs_pfcp_xact_cycle(ogs_pfcp_xact_t *xact);
void ogs_pfcp_xact_delete_all(ogs_pfcp_node_t *node);
int ogs_pfcp_xact_update_tx(ogs_pfcp_xact_t *xact,

View File

@ -85,6 +85,8 @@ extern "C" {
#define OGS_MAX_NUM_OF_ALGORITHM 8
#define OGS_MAX_5G_GUTI_LEN 28
#define OGS_MAX_NUM_OF_SERVED_GUMMEI 8 /* maxnoofRATs: 8 */
#define OGS_MAX_NUM_OF_SERVED_GUAMI 256 /* maxnoofServedGUAMIs: 256 */
#define OGS_MAX_NUM_OF_SUPPORTED_TA 256 /* maxnoofTACs: 256 */
@ -271,10 +273,11 @@ ogs_amf_id_t *ogs_amf_id_build(ogs_amf_id_t *amf_id,
#define OGS_PROTECTION_SCHEME_PROFILE_B 2
/************************************
* SUPI/GPSI */
* SUPI/GPSI/GUTI */
#define OGS_ID_SUPI_TYPE_IMSI "imsi"
#define OGS_ID_GPSI_TYPE_MSISDN "msisdn"
#define OGS_ID_SUPI_TYPE_IMEISV "imeisv"
#define OGS_ID_5G_GUTI_TYPE "5g-guti"
char *ogs_id_get_type(const char *str);
char *ogs_id_get_value(const char *str);

View File

@ -29,6 +29,7 @@ static OGS_POOL(xact_pool, ogs_sbi_xact_t);
static OGS_POOL(subscription_spec_pool, ogs_sbi_subscription_spec_t);
static OGS_POOL(subscription_data_pool, ogs_sbi_subscription_data_t);
static OGS_POOL(smf_info_pool, ogs_sbi_smf_info_t);
static OGS_POOL(amf_info_pool, ogs_sbi_amf_info_t);
static OGS_POOL(nf_info_pool, ogs_sbi_nf_info_t);
void ogs_sbi_context_init(OpenAPI_nf_type_e nf_type)
@ -61,6 +62,7 @@ void ogs_sbi_context_init(OpenAPI_nf_type_e nf_type)
ogs_pool_init(&subscription_data_pool, ogs_app()->pool.subscription);
ogs_pool_init(&smf_info_pool, ogs_app()->pool.nf);
ogs_pool_init(&amf_info_pool, ogs_app()->pool.nf);
ogs_pool_init(&nf_info_pool, ogs_app()->pool.nf * OGS_MAX_NUM_OF_NF_INFO);
@ -107,6 +109,7 @@ void ogs_sbi_context_final(void)
ogs_pool_final(&nf_instance_pool);
ogs_pool_final(&nf_service_pool);
ogs_pool_final(&smf_info_pool);
ogs_pool_final(&amf_info_pool);
ogs_pool_final(&nf_info_pool);
@ -1530,7 +1533,13 @@ ogs_sbi_nf_info_t *ogs_sbi_nf_info_add(
static void amf_info_free(ogs_sbi_amf_info_t *amf_info)
{
/* Nothing */
ogs_assert(amf_info);
amf_info->num_of_guami = 0;
amf_info->num_of_nr_tai = 0;
amf_info->num_of_nr_tai_range = 0;
ogs_pool_free(&amf_info_pool, amf_info);
}
static void smf_info_free(ogs_sbi_smf_info_t *smf_info)
@ -1621,6 +1630,26 @@ ogs_sbi_nf_info_t *ogs_sbi_nf_info_find(
return NULL;
}
bool ogs_sbi_check_amf_info_guami(
ogs_sbi_amf_info_t *amf_info, ogs_guami_t *guami)
{
int i;
ogs_assert(amf_info);
ogs_assert(guami);
for (i = 0; i < amf_info->num_of_guami; i++) {
if ((memcmp(&amf_info->guami[i].amf_id, &guami->amf_id,
sizeof(ogs_amf_id_t)) == 0) &&
(memcmp(&amf_info->guami[i].plmn_id, &guami->plmn_id,
OGS_PLMN_ID_LEN) == 0)) {
return true;
}
}
return false;
}
bool ogs_sbi_check_smf_info_slice(
ogs_sbi_smf_info_t *smf_info, ogs_s_nssai_t *s_nssai, char *dnn)
{
@ -1964,6 +1993,13 @@ bool ogs_sbi_discovery_option_is_matched(
}
switch (nf_info->nf_type) {
case OpenAPI_nf_type_AMF:
if (requester_nf_type == OpenAPI_nf_type_AMF &&
discovery_option->target_guami &&
ogs_sbi_check_amf_info_guami(&nf_info->amf,
discovery_option->target_guami) == false)
return false;
break;
case OpenAPI_nf_type_SMF:
if (discovery_option->num_of_snssais && discovery_option->dnn &&
ogs_sbi_check_smf_info_slice(&nf_info->smf,

View File

@ -341,8 +341,8 @@ typedef struct ogs_sbi_sepp_info_s {
} ogs_sbi_sepp_info_t;
typedef struct ogs_sbi_amf_info_s {
int amf_set_id;
int amf_region_id;
uint8_t amf_set_id;
uint16_t amf_region_id;
int num_of_guami;
ogs_guami_t guami[OGS_MAX_NUM_OF_SERVED_GUAMI];
@ -437,6 +437,8 @@ void ogs_sbi_nf_info_remove_all(ogs_list_t *list);
ogs_sbi_nf_info_t *ogs_sbi_nf_info_find(
ogs_list_t *list, OpenAPI_nf_type_e nf_type);
bool ogs_sbi_check_amf_info_guami(
ogs_sbi_amf_info_t *amf_info, ogs_guami_t *guami);
bool ogs_sbi_check_smf_info_slice(
ogs_sbi_smf_info_t *smf_info, ogs_s_nssai_t *s_nssai, char *dnn);
bool ogs_sbi_check_smf_info_tai(

View File

@ -189,6 +189,10 @@ void ogs_sbi_message_free(ogs_sbi_message_t *message)
OpenAPI_sec_negotiate_req_data_free(message->SecNegotiateReqData);
if (message->SecNegotiateRspData)
OpenAPI_sec_negotiate_rsp_data_free(message->SecNegotiateRspData);
if (message->UeContextTransferReqData)
OpenAPI_ue_context_transfer_req_data_free(message->UeContextTransferReqData);
if (message->UeContextTransferRspData)
OpenAPI_ue_context_transfer_rsp_data_free(message->UeContextTransferRspData);
/* HTTP Part */
for (i = 0; i < message->num_of_part; i++) {
@ -282,6 +286,7 @@ ogs_sbi_request_t *ogs_sbi_build_request(ogs_sbi_message_t *message)
int i;
ogs_sbi_request_t *request = NULL;
OpenAPI_nf_type_e nf_type = OpenAPI_nf_type_NULL;
char sender_timestamp[OGS_SBI_RFC7231_DATE_LEN];
char *max_rsp_time = NULL;
@ -389,6 +394,18 @@ ogs_sbi_request_t *ogs_sbi_build_request(ogs_sbi_message_t *message)
OGS_SBI_PARAM_REQUESTER_NF_INSTANCE_ID,
discovery_option->requester_nf_instance_id);
}
if (discovery_option->target_guami) {
char *v = ogs_sbi_discovery_option_build_guami(discovery_option);
if (v) {
ogs_sbi_header_set(request->http.params,
OGS_SBI_PARAM_GUAMI, v);
ogs_free(v);
} else {
ogs_warn("build failed: service-names[%d:%s]",
discovery_option->num_of_service_names,
discovery_option->service_names[0]);
}
}
if (ogs_sbi_self()->discovery_config.no_service_names == false &&
discovery_option->num_of_service_names) {
@ -817,9 +834,14 @@ int ogs_sbi_parse_request(
ogs_sbi_discovery_option_parse_snssais(discovery_option, v);
discovery_option_presence = true;
}
} else if (!strcmp(ogs_hash_this_key(hi), OGS_SBI_PARAM_GUAMI)) {
char *v = ogs_hash_this_val(hi);
if (v) {
ogs_sbi_discovery_option_parse_guami(discovery_option, v);
discovery_option_presence = true;
}
} else if (!strcmp(ogs_hash_this_key(hi), OGS_SBI_PARAM_DNN)) {
char *v = ogs_hash_this_val(hi);
if (v) {
ogs_sbi_discovery_option_set_dnn(discovery_option, v);
discovery_option_presence = true;
@ -1340,6 +1362,14 @@ static char *build_json(ogs_sbi_message_t *message)
item = OpenAPI_sec_negotiate_rsp_data_convertToJSON(
message->SecNegotiateRspData);
ogs_assert(item);
} else if (message->UeContextTransferReqData) {
item = OpenAPI_ue_context_transfer_req_data_convertToJSON(
message->UeContextTransferReqData);
ogs_assert(item);
} else if (message->UeContextTransferRspData) {
item = OpenAPI_ue_context_transfer_rsp_data_convertToJSON(
message->UeContextTransferRspData);
ogs_assert(item);
}
if (item) {
@ -2082,6 +2112,27 @@ static int parse_json(ogs_sbi_message_t *message,
}
break;
CASE(OGS_SBI_RESOURCE_NAME_TRANSFER)
if (message->res_status == 0) {
message->UeContextTransferReqData =
OpenAPI_ue_context_transfer_req_data_parseFromJSON(item);
if (!message->UeContextTransferReqData) {
rv = OGS_ERROR;
ogs_error("JSON parse error");
}
} else if (message->res_status == OGS_SBI_HTTP_STATUS_OK) {
message->UeContextTransferRspData =
OpenAPI_ue_context_transfer_rsp_data_parseFromJSON(item);
if (!message->UeContextTransferRspData) {
rv = OGS_ERROR;
ogs_error("JSON parse error");
}
} else {
ogs_error("HTTP ERROR Status : %d",
message->res_status);
}
break;
DEFAULT
rv = OGS_ERROR;
ogs_error("Unknown resource name [%s]",
@ -2889,6 +2940,8 @@ void ogs_sbi_discovery_option_free(
ogs_free(discovery_option->requester_nf_instance_id);
if (discovery_option->dnn)
ogs_free(discovery_option->dnn);
if (discovery_option->target_guami)
ogs_free(discovery_option->target_guami);
for (i = 0; i < discovery_option->num_of_service_names; i++)
ogs_free(discovery_option->service_names[i]);
@ -3129,6 +3182,71 @@ void ogs_sbi_discovery_option_parse_snssais(
ogs_free(v);
}
char *ogs_sbi_discovery_option_build_guami(
ogs_sbi_discovery_option_t *discovery_option)
{
OpenAPI_guami_t *Guami = NULL;
cJSON *guamiItem = NULL;
char *v = NULL;
ogs_assert(discovery_option);
ogs_assert(discovery_option->target_guami);
Guami = ogs_sbi_build_guami(discovery_option->target_guami);
ogs_assert(Guami);
guamiItem = OpenAPI_guami_convertToJSON(Guami);
ogs_assert(guamiItem);
ogs_sbi_free_guami(Guami);
v = cJSON_PrintUnformatted(guamiItem);
ogs_expect(v);
cJSON_Delete(guamiItem);
return v;
}
void ogs_sbi_discovery_option_parse_guami(
ogs_sbi_discovery_option_t *discovery_option, char *guami)
{
OpenAPI_guami_t *Guami = NULL;
cJSON *guamItem = NULL;
char *v = NULL;
ogs_assert(discovery_option);
ogs_assert(guami);
v = ogs_sbi_url_decode(guami);
if (!v) {
ogs_error("ogs_sbi_url_decode() failed : guami[%s]", guami);
return;
}
guamItem = cJSON_Parse(v);
if (!guamItem) {
ogs_error("Cannot parse guami[%s]", guami);
ogs_free(v);
return;
}
Guami = OpenAPI_guami_parseFromJSON(guamItem);
if (Guami) {
ogs_guami_t *ogs_guami = NULL;
discovery_option->target_guami = ogs_malloc(sizeof(*ogs_guami));
ogs_assert(discovery_option->target_guami);
ogs_sbi_parse_guami(discovery_option->target_guami, Guami);
OpenAPI_guami_free(Guami);
} else {
ogs_error("OpenAPI_guami_parseFromJSON() failed : guami[%s]",
guami);
}
cJSON_Delete(guamItem);
ogs_free(v);
}
void ogs_sbi_discovery_option_set_tai(
ogs_sbi_discovery_option_t *discovery_option, ogs_5gs_tai_t *tai)
{

View File

@ -124,6 +124,7 @@ extern "C" {
#define OGS_SBI_RESOURCE_NAME_UE_CONTEXTS "ue-contexts"
#define OGS_SBI_RESOURCE_NAME_N1_N2_MESSAGES "n1-n2-messages"
#define OGS_SBI_RESOURCE_NAME_TRANSFER "transfer"
#define OGS_SBI_RESOURCE_NAME_SM_CONTEXT_STATUS "sm-context-status"
#define OGS_SBI_RESOURCE_NAME_AM_POLICY_NOTIFY "am-policy-notify"
@ -295,6 +296,8 @@ extern "C" {
OGS_SBI_CUSTOM_DISCOVERY_COMMON OGS_SBI_PARAM_REQUESTER_PLMN_LIST
#define OGS_SBI_CUSTOM_DISCOVERY_REQUESTER_FEATURES \
OGS_SBI_CUSTOM_DISCOVERY_COMMON OGS_SBI_PARAM_REQUESTER_FEATURES
#define OGS_SBI_CUSTOM_DISCOVERY_GUAMI \
OGS_SBI_CUSTOM_DISCOVERY_COMMON OGS_SBI_PARAM_GUAMI
#define OGS_SBI_CUSTOM_PRODUCER_ID \
OGS_SBI_CUSTOM_3GPP_COMMON "Producer-Id"
#define OGS_SBI_CUSTOM_OCI \
@ -330,6 +333,7 @@ extern "C" {
#define OGS_SBI_PARAM_PLMN_ID "plmn-id"
#define OGS_SBI_PARAM_SINGLE_NSSAI "single-nssai"
#define OGS_SBI_PARAM_SNSSAI "snssai"
#define OGS_SBI_PARAM_GUAMI "guami"
#define OGS_SBI_PARAM_SNSSAIS "snssais"
#define OGS_SBI_PARAM_TAI "tai"
#define OGS_SBI_PARAM_SLICE_INFO_REQUEST_FOR_PDU_SESSION \
@ -431,6 +435,8 @@ typedef struct ogs_sbi_discovery_option_s {
bool tai_presence;
ogs_5gs_tai_t tai;
ogs_guami_t *target_guami;
int num_of_target_plmn_list;
ogs_plmn_id_t target_plmn_list[OGS_MAX_NUM_OF_PLMN];
int num_of_requester_plmn_list;
@ -542,6 +548,8 @@ typedef struct ogs_sbi_message_s {
OpenAPI_smf_registration_t *SmfRegistration;
OpenAPI_sec_negotiate_req_data_t *SecNegotiateReqData;
OpenAPI_sec_negotiate_rsp_data_t *SecNegotiateRspData;
OpenAPI_ue_context_transfer_req_data_t *UeContextTransferReqData;
OpenAPI_ue_context_transfer_rsp_data_t *UeContextTransferRspData;
ogs_sbi_links_t *links;
@ -641,6 +649,11 @@ char *ogs_sbi_discovery_option_build_snssais(
void ogs_sbi_discovery_option_parse_snssais(
ogs_sbi_discovery_option_t *discovery_option, char *snssais);
char *ogs_sbi_discovery_option_build_guami(
ogs_sbi_discovery_option_t *discovery_option);
void ogs_sbi_discovery_option_parse_guami(
ogs_sbi_discovery_option_t *discovery_option, char *guami);
void ogs_sbi_discovery_option_set_tai(
ogs_sbi_discovery_option_t *discovery_option, ogs_5gs_tai_t *tai);
char *ogs_sbi_discovery_option_build_tai(

View File

@ -27,6 +27,8 @@ static void handle_scp_info(
ogs_sbi_nf_instance_t *nf_instance, OpenAPI_scp_info_t *ScpInfo);
static void handle_sepp_info(
ogs_sbi_nf_instance_t *nf_instance, OpenAPI_sepp_info_t *SeppInfo);
static void handle_amf_info(
ogs_sbi_nf_instance_t *nf_instance, OpenAPI_amf_info_t *AmfInfo);
void ogs_nnrf_nfm_handle_nf_register(
ogs_sbi_nf_instance_t *nf_instance, ogs_sbi_message_t *recvmsg)
@ -256,7 +258,14 @@ void ogs_nnrf_nfm_handle_nf_profile(
if (SmfInfoMap && SmfInfoMap->value)
handle_smf_info(nf_instance, SmfInfoMap->value);
}
if (NFProfile->amf_info)
handle_amf_info(nf_instance, NFProfile->amf_info);
OpenAPI_list_for_each(NFProfile->amf_info_list, node) {
OpenAPI_map_t *AmfInfoMap = node->data;
if (AmfInfoMap && AmfInfoMap->value)
handle_amf_info(nf_instance, AmfInfoMap->value);
}
if (NFProfile->scp_info)
handle_scp_info(nf_instance, NFProfile->scp_info);
if (NFProfile->sepp_info)
@ -653,6 +662,100 @@ static void handle_sepp_info(
}
}
static void handle_amf_info(
ogs_sbi_nf_instance_t *nf_instance, OpenAPI_amf_info_t *AmfInfo)
{
ogs_sbi_nf_info_t *nf_info = NULL;
OpenAPI_list_t *GuamiList = NULL;
OpenAPI_guami_t *GuamiAmfInfoItem = NULL;
OpenAPI_list_t *TaiList = NULL;
OpenAPI_tai_t *TaiItem = NULL;
OpenAPI_list_t *TaiRangeList = NULL;
OpenAPI_tai_range_t *TaiRangeItem = NULL;
OpenAPI_list_t *TacRangeList = NULL;
OpenAPI_tac_range_t *TacRangeItem = NULL;
OpenAPI_lnode_t *node = NULL, *node2 = NULL;
ogs_assert(nf_instance);
ogs_assert(AmfInfo);
nf_info = ogs_sbi_nf_info_add(
&nf_instance->nf_info_list, OpenAPI_nf_type_AMF);
ogs_assert(nf_info);
nf_info->amf.amf_set_id = ogs_uint64_from_string(AmfInfo->amf_set_id);
nf_info->amf.amf_region_id = ogs_uint64_from_string(AmfInfo->amf_region_id);
GuamiList = AmfInfo->guami_list;
OpenAPI_list_for_each(GuamiList, node) {
GuamiAmfInfoItem = node->data;
if (GuamiAmfInfoItem) {
ogs_assert(nf_info->amf.num_of_guami < OGS_MAX_NUM_OF_SERVED_GUAMI);
if (GuamiAmfInfoItem->amf_id && GuamiAmfInfoItem->plmn_id &&
GuamiAmfInfoItem->plmn_id->mnc &&
GuamiAmfInfoItem->plmn_id->mcc) {
ogs_sbi_parse_guami(
&nf_info->amf.guami[nf_info->amf.num_of_guami],
GuamiAmfInfoItem);
nf_info->amf.num_of_guami++;
}
}
}
TaiList = AmfInfo->tai_list;
OpenAPI_list_for_each(TaiList, node) {
TaiItem = node->data;
if (TaiItem && TaiItem->plmn_id && TaiItem->tac) {
ogs_5gs_tai_t *nr_tai = NULL;
ogs_assert(nf_info->amf.num_of_nr_tai < OGS_MAX_NUM_OF_TAI);
nr_tai = &nf_info->amf.nr_tai[nf_info->amf.num_of_nr_tai];
ogs_assert(nr_tai);
ogs_sbi_parse_plmn_id(&nr_tai->plmn_id, TaiItem->plmn_id);
nr_tai->tac = ogs_uint24_from_string(TaiItem->tac);
nf_info->amf.num_of_nr_tai++;
}
}
TaiRangeList = AmfInfo->tai_range_list;
OpenAPI_list_for_each(TaiRangeList, node) {
TaiRangeItem = node->data;
if (TaiRangeItem && TaiRangeItem->plmn_id &&
TaiRangeItem->tac_range_list) {
ogs_assert(nf_info->amf.num_of_nr_tai_range <
OGS_MAX_NUM_OF_TAI);
ogs_sbi_parse_plmn_id(
&nf_info->amf.nr_tai_range
[nf_info->amf.num_of_nr_tai_range].plmn_id,
TaiRangeItem->plmn_id);
TacRangeList = TaiRangeItem->tac_range_list;
OpenAPI_list_for_each(TacRangeList, node2) {
TacRangeItem = node2->data;
if (TacRangeItem &&
TacRangeItem->start && TacRangeItem->end) {
int tac_index = nf_info->amf.nr_tai_range
[nf_info->amf.num_of_nr_tai_range].num_of_tac_range;
ogs_assert(tac_index < OGS_MAX_NUM_OF_TAI);
nf_info->amf.nr_tai_range
[nf_info->amf.num_of_nr_tai_range].start[tac_index] =
ogs_uint24_from_string(TacRangeItem->start);
nf_info->amf.nr_tai_range
[nf_info->amf.num_of_nr_tai_range].end[tac_index] =
ogs_uint24_from_string(TacRangeItem->end);
nf_info->amf.nr_tai_range
[nf_info->amf.num_of_nr_tai_range].num_of_tac_range++;
}
}
nf_info->amf.num_of_nr_tai_range++;
}
}
}
static void handle_validity_time(
ogs_sbi_subscription_data_t *subscription_data,
char *validity_time, const char *action)

View File

@ -84,6 +84,8 @@
#include "model/sec_negotiate_rsp_data.h"
#include "model/patch_item.h"
#include "model/ue_authentication_ctx.h"
#include "model/ue_context_transfer_req_data.h"
#include "model/ue_context_transfer_rsp_data.h"
#include "custom/links.h"

View File

@ -422,6 +422,33 @@ int ogs_sbi_discover_and_send(ogs_sbi_xact_t *xact)
discovery_option->tai.tac.v);
}
if (discovery_option && discovery_option->target_guami) {
bool rc = false;
char *v = ogs_sbi_discovery_option_build_guami(discovery_option);
ogs_expect(v);
if (v) {
char *encoded = ogs_sbi_url_encode(v);
ogs_expect(encoded);
if (encoded) {
ogs_sbi_header_set(request->http.headers,
OGS_SBI_CUSTOM_DISCOVERY_GUAMI, encoded);
ogs_free(encoded);
rc = true;
}
ogs_free(v);
}
if (rc == false)
ogs_error("build failed: guami[PLMN_ID:%06x,AMF_ID:%x]",
ogs_plmn_id_hexdump(
&discovery_option->target_guami->plmn_id),
ogs_amf_id_hexdump(
&discovery_option->target_guami->amf_id));
}
if (discovery_option &&
discovery_option->requester_features) {
char *v = ogs_uint64_to_string(

View File

@ -180,6 +180,22 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
END
break;
CASE(OGS_SBI_RESOURCE_NAME_TRANSFER)
SWITCH(sbi_message.h.method)
CASE(OGS_SBI_HTTP_METHOD_POST)
amf_namf_comm_handle_ue_context_transfer_request(
stream, &sbi_message);
break;
DEFAULT
ogs_error("Invalid HTTP method [%s]",
sbi_message.h.method);
ogs_assert(true ==
ogs_sbi_server_send_error(stream,
OGS_SBI_HTTP_STATUS_FORBIDDEN, &sbi_message,
"Invalid HTTP method", sbi_message.h.method));
END
break;
DEFAULT
ogs_error("Invalid resource name [%s]",
sbi_message.h.resource.component[2]);
@ -375,6 +391,7 @@ void amf_state_operational(ogs_fsm_t *s, amf_event_t *e)
CASE(OGS_SBI_SERVICE_NAME_NUDM_UECM)
CASE(OGS_SBI_SERVICE_NAME_NUDM_SDM)
CASE(OGS_SBI_SERVICE_NAME_NPCF_AM_POLICY_CONTROL)
CASE(OGS_SBI_SERVICE_NAME_NAMF_COMM)
sbi_xact = e->h.sbi.data;
ogs_assert(sbi_xact);

View File

@ -40,6 +40,7 @@ static void stats_add_ran_ue(void);
static void stats_remove_ran_ue(void);
static void stats_add_amf_session(void);
static void stats_remove_amf_session(void);
static bool amf_namf_comm_parse_guti(ogs_nas_5gs_guti_t *guti, char *ue_context_id);
void amf_context_init(void)
{
@ -1955,6 +1956,105 @@ amf_ue_t *amf_ue_find_by_message(ogs_nas_5gs_message_t *message)
return amf_ue;
}
static bool amf_namf_comm_parse_guti(ogs_nas_5gs_guti_t *guti, char *ue_context_id)
{
#define MIN_LENGTH_OF_MNC 2
#define MAX_LENGTH_OF_MNC 3
#define LENGTH_OF_MCC 3
#define LENGTH_OF_AMF_ID 6
#define LENGTH_OF_TMSI 8
char amf_id_string[LENGTH_OF_AMF_ID + 1];
char tmsi_string[LENGTH_OF_TMSI + 1];
char mcc_string[LENGTH_OF_MCC + 1];
char mnc_string[MAX_LENGTH_OF_MNC + 1];
OpenAPI_plmn_id_t Plmn_id;
ogs_plmn_id_t plmn_id;
/* TS29.518 6.1.3.2.2 Guti pattern (27 or 28 characters):
"5g-guti-[0-9]{5,6}[0-9a-fA-F]{14}" */
short index = 8; /* start parsing guti after "5g-guti-" */
strncpy(mcc_string, &ue_context_id[index], LENGTH_OF_MCC);
mcc_string[LENGTH_OF_MCC] = '\0';
index += LENGTH_OF_MCC;
if (strlen(ue_context_id) == OGS_MAX_5G_GUTI_LEN - 1) {
/* mnc is 2 characters long */
mnc_string[MIN_LENGTH_OF_MNC] = '\0';
strncpy(mnc_string, &ue_context_id[index], MIN_LENGTH_OF_MNC);
index += MIN_LENGTH_OF_MNC;
} else if (strlen(ue_context_id) == OGS_MAX_5G_GUTI_LEN) {
/* mnc is 3 characters long */
mnc_string[MAX_LENGTH_OF_MNC] = '\0';
strncpy(mnc_string, &ue_context_id[index], MAX_LENGTH_OF_MNC);
index += MAX_LENGTH_OF_MNC;
} else {
ogs_error("Invalid Ue context id");
return false;
}
strncpy(amf_id_string, &ue_context_id[index], LENGTH_OF_AMF_ID);
amf_id_string[LENGTH_OF_AMF_ID] = '\0';
index += LENGTH_OF_AMF_ID;
strncpy(tmsi_string, &ue_context_id[index], LENGTH_OF_TMSI);
tmsi_string[LENGTH_OF_TMSI] = '\0';
memset(&Plmn_id, 0, sizeof(Plmn_id));
Plmn_id.mcc = mcc_string;
Plmn_id.mnc = mnc_string;
memset(&plmn_id, 0, sizeof(plmn_id));
ogs_sbi_parse_plmn_id(&plmn_id, &Plmn_id);
ogs_nas_from_plmn_id(&guti->nas_plmn_id, &plmn_id);
ogs_amf_id_from_string(&guti->amf_id, amf_id_string);
guti->m_tmsi = (u_int32_t)strtol(tmsi_string, NULL, 16);
return true;
}
amf_ue_t *amf_ue_find_by_ue_context_id(char *ue_context_id)
{
amf_ue_t *amf_ue = NULL;
ogs_assert(ue_context_id);
if (strncmp(ue_context_id, OGS_ID_SUPI_TYPE_IMSI,
strlen(OGS_ID_SUPI_TYPE_IMSI)) == 0) {
amf_ue = amf_ue_find_by_supi(ue_context_id);
if (!amf_ue) {
ogs_info("[%s] Unknown UE by SUPI", ue_context_id);
return NULL;
}
} else if (strncmp(ue_context_id, OGS_ID_5G_GUTI_TYPE,
strlen(OGS_ID_5G_GUTI_TYPE)) == 0) {
ogs_nas_5gs_guti_t guti;
memset(&guti, 0, sizeof(guti));
if (amf_namf_comm_parse_guti(&guti, ue_context_id) == false) {
ogs_error("amf_namf_comm_parse_guti() failed");
return NULL;
}
amf_ue = amf_ue_find_by_guti(&guti);
if (!amf_ue) {
ogs_info("[%s] Unknown UE by GUTI", ue_context_id);
return NULL;
}
} else {
ogs_error("Unsupported UE context ID type");
return NULL;
}
return amf_ue;
}
void amf_ue_set_suci(amf_ue_t *amf_ue,
ogs_nas_5gs_mobile_identity_t *mobile_identity)
{

View File

@ -749,6 +749,7 @@ void amf_ue_fsm_fini(amf_ue_t *amf_ue);
amf_ue_t *amf_ue_find_by_guti(ogs_nas_5gs_guti_t *nas_guti);
amf_ue_t *amf_ue_find_by_suci(char *suci);
amf_ue_t *amf_ue_find_by_supi(char *supi);
amf_ue_t *amf_ue_find_by_ue_context_id(char *ue_context_id);
amf_ue_t *amf_ue_find_by_message(ogs_nas_5gs_message_t *message);
void amf_ue_set_suci(amf_ue_t *amf_ue,

View File

@ -29,7 +29,7 @@
#define OGS_LOG_DOMAIN __gmm_log_domain
static ogs_nas_5gmm_cause_t gmm_handle_nas_message_container(
amf_ue_t *amf_ue, uint8_t message_type,
ran_ue_t *ran_ue, amf_ue_t *amf_ue, uint8_t message_type,
ogs_nas_message_container_t *nas_message_container);
static uint8_t gmm_cause_from_access_control(ogs_plmn_id_t *plmn_id);
@ -339,7 +339,8 @@ ogs_nas_5gmm_cause_t gmm_handle_registration_request(amf_ue_t *amf_ue,
return OGS_5GMM_CAUSE_REQUEST_ACCEPTED;
}
ogs_nas_5gmm_cause_t gmm_handle_registration_update(amf_ue_t *amf_ue,
ogs_nas_5gmm_cause_t gmm_handle_registration_update(
ran_ue_t *ran_ue, amf_ue_t *amf_ue,
ogs_nas_5gs_registration_request_t *registration_request)
{
amf_sess_t *sess = NULL;
@ -352,6 +353,7 @@ ogs_nas_5gmm_cause_t gmm_handle_registration_update(amf_ue_t *amf_ue,
ogs_nas_5gs_update_type_t *update_type = NULL;
ogs_assert(amf_ue);
ogs_assert(ran_ue);
ogs_assert(registration_request);
last_visited_registered_tai =
@ -376,7 +378,7 @@ ogs_nas_5gmm_cause_t gmm_handle_registration_update(amf_ue_t *amf_ue,
OGS_NAS_5GS_REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT) {
return gmm_handle_nas_message_container(
amf_ue, OGS_NAS_5GS_REGISTRATION_REQUEST,
ran_ue, amf_ue, OGS_NAS_5GS_REGISTRATION_REQUEST,
&registration_request->nas_message_container);
}
@ -472,7 +474,7 @@ ogs_nas_5gmm_cause_t gmm_handle_registration_update(amf_ue_t *amf_ue,
if ((psimask & (1 << sess->psi)) == 0) {
if (SESSION_CONTEXT_IN_SMF(sess))
amf_sbi_send_release_session(
sess, AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT);
ran_ue, sess, AMF_RELEASE_SM_CONTEXT_REGISTRATION_ACCEPT);
}
}
}
@ -491,7 +493,8 @@ ogs_nas_5gmm_cause_t gmm_handle_registration_update(amf_ue_t *amf_ue,
if (psimask & (1 << sess->psi)) {
if (SESSION_CONTEXT_IN_SMF(sess))
amf_sbi_send_activating_session(
sess, AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST);
ran_ue, sess,
AMF_UPDATE_SM_CONTEXT_REGISTRATION_REQUEST);
}
}
}
@ -653,7 +656,8 @@ ogs_nas_5gmm_cause_t gmm_handle_service_request(amf_ue_t *amf_ue,
return OGS_5GMM_CAUSE_REQUEST_ACCEPTED;
}
ogs_nas_5gmm_cause_t gmm_handle_service_update(amf_ue_t *amf_ue,
ogs_nas_5gmm_cause_t gmm_handle_service_update(
ran_ue_t *ran_ue, amf_ue_t *amf_ue,
ogs_nas_5gs_service_request_t *service_request)
{
amf_sess_t *sess = NULL;
@ -665,6 +669,8 @@ ogs_nas_5gmm_cause_t gmm_handle_service_update(amf_ue_t *amf_ue,
ogs_nas_allowed_pdu_session_status_t *allowed_pdu_session_status = NULL;
ogs_assert(amf_ue);
ogs_assert(ran_ue);
ogs_assert(service_request);
uplink_data_status = &service_request->uplink_data_status;
ogs_assert(uplink_data_status);
@ -677,7 +683,7 @@ ogs_nas_5gmm_cause_t gmm_handle_service_update(amf_ue_t *amf_ue,
OGS_NAS_5GS_SERVICE_REQUEST_NAS_MESSAGE_CONTAINER_PRESENT) {
return gmm_handle_nas_message_container(
amf_ue, OGS_NAS_5GS_SERVICE_REQUEST,
ran_ue, amf_ue, OGS_NAS_5GS_SERVICE_REQUEST,
&service_request->nas_message_container);
}
@ -712,7 +718,7 @@ ogs_nas_5gmm_cause_t gmm_handle_service_update(amf_ue_t *amf_ue,
if ((psimask & (1 << sess->psi)) == 0) {
if (SESSION_CONTEXT_IN_SMF(sess))
amf_sbi_send_release_session(
sess, AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT);
ran_ue, sess, AMF_RELEASE_SM_CONTEXT_SERVICE_ACCEPT);
}
}
}
@ -739,7 +745,8 @@ ogs_nas_5gmm_cause_t gmm_handle_service_update(amf_ue_t *amf_ue,
if (psimask & (1 << sess->psi)) {
if (SESSION_CONTEXT_IN_SMF(sess))
amf_sbi_send_activating_session(
sess, AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST);
ran_ue, sess,
AMF_UPDATE_SM_CONTEXT_SERVICE_REQUEST);
}
}
}
@ -757,9 +764,12 @@ int gmm_handle_deregistration_request(amf_ue_t *amf_ue,
ogs_nas_5gs_deregistration_request_from_ue_t *deregistration_request)
{
int r, state, xact_count = 0;
ran_ue_t *ran_ue = NULL;
ogs_nas_de_registration_type_t *de_registration_type = NULL;
ogs_assert(amf_ue);
ran_ue = ran_ue_cycle(amf_ue->ran_ue);
ogs_assert(ran_ue);
ogs_assert(deregistration_request);
de_registration_type = &deregistration_request->de_registration_type;
@ -790,7 +800,7 @@ int gmm_handle_deregistration_request(amf_ue_t *amf_ue,
xact_count = amf_sess_xact_count(amf_ue);
state = AMF_UE_INITIATED_DE_REGISTERED;
amf_sbi_send_release_all_sessions(amf_ue, state);
amf_sbi_send_release_all_sessions(ran_ue, amf_ue, state);
if (!AMF_SESSION_RELEASE_PENDING(amf_ue) &&
amf_sess_xact_count(amf_ue) == xact_count) {
@ -884,6 +894,7 @@ ogs_nas_5gmm_cause_t gmm_handle_identity_response(amf_ue_t *amf_ue,
ogs_assert(amf_ue);
ran_ue = ran_ue_cycle(amf_ue->ran_ue);
ogs_assert(ran_ue);
ogs_assert(identity_response);
mobile_identity = &identity_response->mobile_identity;
@ -940,12 +951,15 @@ ogs_nas_5gmm_cause_t gmm_handle_identity_response(amf_ue_t *amf_ue,
}
ogs_nas_5gmm_cause_t gmm_handle_security_mode_complete(amf_ue_t *amf_ue,
ogs_nas_5gs_security_mode_complete_t *security_mode_complete)
ogs_nas_5gs_security_mode_complete_t *security_mode_complete)
{
ran_ue_t *ran_ue = NULL;
ogs_nas_5gs_mobile_identity_t *imeisv = NULL;
ogs_nas_mobile_identity_imeisv_t *mobile_identity_imeisv = NULL;
ogs_assert(amf_ue);
ran_ue = ran_ue_cycle(amf_ue->ran_ue);
ogs_assert(ran_ue);
ogs_assert(security_mode_complete);
/*
@ -1021,7 +1035,7 @@ ogs_nas_5gmm_cause_t gmm_handle_security_mode_complete(amf_ue_t *amf_ue,
OGS_NAS_5GS_SECURITY_MODE_COMPLETE_NAS_MESSAGE_CONTAINER_PRESENT) {
return gmm_handle_nas_message_container(
amf_ue, OGS_NAS_5GS_SECURITY_MODE_COMPLETE,
ran_ue, amf_ue, OGS_NAS_5GS_SECURITY_MODE_COMPLETE,
&security_mode_complete->nas_message_container);
}
@ -1316,14 +1330,15 @@ int gmm_handle_ul_nas_transport(ran_ue_t *ran_ue, amf_ue_t *amf_ue,
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION,
discovery_option,
amf_nsmf_pdusession_build_create_sm_context,
sess, AMF_CREATE_SM_CONTEXT_NO_STATE, NULL);
ran_ue, sess, AMF_CREATE_SM_CONTEXT_NO_STATE, NULL);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else {
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NNSSF_NSSELECTION,
discovery_option,
amf_nnssf_nsselection_build_get, sess, 0, NULL);
amf_nnssf_nsselection_build_get,
ran_ue, sess, 0, NULL);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
@ -1337,7 +1352,8 @@ int gmm_handle_ul_nas_transport(ran_ue_t *ran_ue, amf_ue_t *amf_ue,
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context,
sess, AMF_UPDATE_SM_CONTEXT_DUPLICATED_PDU_SESSION_ID,
ran_ue, sess,
AMF_UPDATE_SM_CONTEXT_DUPLICATED_PDU_SESSION_ID,
&param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -1366,7 +1382,8 @@ int gmm_handle_ul_nas_transport(ran_ue_t *ran_ue, amf_ue_t *amf_ue,
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context,
sess, AMF_UPDATE_SM_CONTEXT_N1_RELEASED, &param);
ran_ue, sess,
AMF_UPDATE_SM_CONTEXT_N1_RELEASED, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else {
@ -1374,7 +1391,7 @@ int gmm_handle_ul_nas_transport(ran_ue_t *ran_ue, amf_ue_t *amf_ue,
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context,
sess, AMF_UPDATE_SM_CONTEXT_MODIFIED, &param);
ran_ue, sess, AMF_UPDATE_SM_CONTEXT_MODIFIED, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
@ -1440,7 +1457,7 @@ int gmm_handle_ul_nas_transport(ran_ue_t *ran_ue, amf_ue_t *amf_ue,
}
static ogs_nas_5gmm_cause_t gmm_handle_nas_message_container(
amf_ue_t *amf_ue, uint8_t message_type,
ran_ue_t *ran_ue, amf_ue_t *amf_ue, uint8_t message_type,
ogs_nas_message_container_t *nas_message_container)
{
int gmm_cause;
@ -1449,6 +1466,7 @@ static ogs_nas_5gmm_cause_t gmm_handle_nas_message_container(
ogs_nas_5gs_message_t nas_message;
ogs_assert(amf_ue);
ogs_assert(ran_ue);
ogs_assert(nas_message_container);
if (!nas_message_container->buffer || !nas_message_container->length) {
@ -1505,12 +1523,12 @@ static ogs_nas_5gmm_cause_t gmm_handle_nas_message_container(
case OGS_NAS_5GS_REGISTRATION_REQUEST:
ogs_debug("Registration request in NAS message container");
gmm_cause = gmm_handle_registration_update(
amf_ue, &nas_message.gmm.registration_request);
ran_ue, amf_ue, &nas_message.gmm.registration_request);
break;
case OGS_NAS_5GS_SERVICE_REQUEST:
ogs_debug("Service request in NAS message container");
gmm_cause = gmm_handle_service_update(
amf_ue, &nas_message.gmm.service_request);
ran_ue, amf_ue, &nas_message.gmm.service_request);
break;
default:
ogs_error("Unknown message [%d]", nas_message.gmm.h.message_type);
@ -1520,6 +1538,243 @@ static ogs_nas_5gmm_cause_t gmm_handle_nas_message_container(
return gmm_cause;
}
static ogs_nas_5gmm_capability_t
amf_namf_comm_base64_decode_5gmm_capability(char *encoded)
{
ogs_nas_5gmm_capability_t gmm_capability;
char *gmm_capability_octets_string = NULL;
uint8_t gmm_capability_iei = 0;
memset(&gmm_capability, 0, sizeof(gmm_capability));
gmm_capability_octets_string =
(char*) ogs_calloc(sizeof(gmm_capability) + 1, sizeof(char));
ogs_assert(gmm_capability_octets_string);
int len = ogs_base64_decode(gmm_capability_octets_string, encoded);
if (len == 0)
ogs_error("Gmm capability not decoded");
ogs_assert(sizeof(gmm_capability_octets_string) <=
sizeof(gmm_capability) + 1);
gmm_capability_iei = // not copied anywhere for now
gmm_capability_octets_string[0];
if (gmm_capability_iei !=
OGS_NAS_5GS_REGISTRATION_REQUEST_5GMM_CAPABILITY_TYPE) {
ogs_error("Type of 5GMM capability IEI is incorrect");
}
memcpy(&gmm_capability,
gmm_capability_octets_string + 1,
sizeof(gmm_capability));
if (gmm_capability_octets_string) {
ogs_free(gmm_capability_octets_string);
}
return gmm_capability;
}
static ogs_nas_ue_security_capability_t
amf_namf_comm_base64_decode_ue_security_capability(char *encoded)
{
ogs_nas_ue_security_capability_t ue_security_capability;
char *ue_security_capability_octets_string = NULL;
uint8_t ue_security_capability_iei = 0;
memset(&ue_security_capability, 0, sizeof(ue_security_capability));
ue_security_capability_octets_string =
(char*) ogs_calloc(sizeof(ue_security_capability), sizeof(char));
ogs_assert(ue_security_capability_octets_string);
ogs_base64_decode(ue_security_capability_octets_string, encoded);
ogs_assert(sizeof(ue_security_capability_octets_string) <=
sizeof(ogs_nas_ue_security_capability_t) + 1);
ue_security_capability_iei = // not copied anywhere for now
ue_security_capability_octets_string[0];
if (ue_security_capability_iei !=
OGS_NAS_5GS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_TYPE) {
ogs_error("UE security capability IEI is incorrect");
}
memcpy(&ue_security_capability, ue_security_capability_octets_string + 1,
sizeof(ue_security_capability));
if (ue_security_capability_octets_string) {
ogs_free(ue_security_capability_octets_string);
}
return ue_security_capability;
}
static void amf_namf_comm_decode_ue_mm_context_list(
amf_ue_t *amf_ue, OpenAPI_list_t *MmContextList) {
OpenAPI_lnode_t *node = NULL;
OpenAPI_list_for_each(MmContextList, node) {
OpenAPI_mm_context_t *MmContext = NULL;
OpenAPI_list_t *AllowedNssaiList = NULL;
OpenAPI_lnode_t *node1 = NULL;
OpenAPI_list_t *NssaiMappingList = NULL;
int num_of_s_nssai = 0;
int num_of_nssai_mapping = 0;
MmContext = node->data;
AllowedNssaiList = MmContext->allowed_nssai;
NssaiMappingList = MmContext->nssai_mapping_list;
OpenAPI_list_for_each(AllowedNssaiList, node1) {
OpenAPI_snssai_t *AllowedNssai = node1->data;
ogs_assert(num_of_s_nssai < OGS_MAX_NUM_OF_SLICE);
amf_ue->allowed_nssai.s_nssai[num_of_s_nssai].sst =
(uint8_t)AllowedNssai->sst;
amf_ue->allowed_nssai.s_nssai[num_of_s_nssai].sd =
ogs_s_nssai_sd_from_string(AllowedNssai->sd);
num_of_s_nssai++;
amf_ue->allowed_nssai.num_of_s_nssai = num_of_s_nssai;
}
OpenAPI_list_for_each(NssaiMappingList, node1) {
OpenAPI_nssai_mapping_t *NssaiMapping = node1->data;
OpenAPI_snssai_t *HSnssai = NssaiMapping->h_snssai;
ogs_assert(num_of_nssai_mapping < OGS_MAX_NUM_OF_SLICE);
amf_ue->allowed_nssai.s_nssai[num_of_nssai_mapping].
mapped_hplmn_sst = HSnssai->sst;
amf_ue->allowed_nssai.s_nssai[num_of_nssai_mapping].
mapped_hplmn_sd = ogs_s_nssai_sd_from_string(HSnssai->sd);
num_of_nssai_mapping++;
}
if (MmContext->ue_security_capability) {
amf_ue->ue_security_capability =
amf_namf_comm_base64_decode_ue_security_capability(
MmContext->ue_security_capability);
}
}
}
static void amf_namf_comm_decode_ue_session_context_list(
amf_ue_t *amf_ue, OpenAPI_list_t *SessionContextList)
{
OpenAPI_lnode_t *node = NULL;
OpenAPI_list_for_each(SessionContextList, node) {
OpenAPI_pdu_session_context_t *PduSessionContext;
PduSessionContext = node->data;
amf_sess_t *sess = NULL;
sess = amf_sess_add(amf_ue, PduSessionContext->pdu_session_id);
ogs_assert(sess);
sess->sm_context_ref = PduSessionContext->sm_context_ref;
if (PduSessionContext->s_nssai) {
memset(&sess->s_nssai, 0, sizeof(sess->s_nssai));
sess->s_nssai.sst = PduSessionContext->s_nssai->sst;
sess->s_nssai.sd = ogs_s_nssai_sd_from_string(
PduSessionContext->s_nssai->sd);
}
if (PduSessionContext->dnn)
sess->dnn = ogs_strdup(PduSessionContext->dnn);
if (PduSessionContext->access_type)
amf_ue->nas.access_type = (int)PduSessionContext->access_type;
}
}
int amf_namf_comm_handle_ue_context_transfer_response(
ogs_sbi_message_t *recvmsg, amf_ue_t *amf_ue)
{
OpenAPI_ue_context_t *UeContext = NULL;
ogs_error("V funkciji amf_namf_comm_handle_ue_context_transfer_response");
if (!recvmsg->UeContextTransferRspData) {
ogs_error("No UeContextTransferRspData");
return OGS_ERROR;
}
if (!recvmsg->UeContextTransferRspData->ue_context) {
ogs_error("No UE context");
return OGS_ERROR;
}
UeContext = recvmsg->UeContextTransferRspData->ue_context;
if (UeContext->supi) {
amf_ue_set_supi(amf_ue, UeContext->supi);
if (!UeContext->supi_unauth_ind){
amf_ue->auth_result = OpenAPI_auth_result_AUTHENTICATION_SUCCESS;
}
}
if (UeContext->pei) {
if (amf_ue->pei)
ogs_free(amf_ue->pei);
amf_ue->pei = ogs_strdup(UeContext->pei);
}
if (UeContext->sub_ue_ambr) {
amf_ue->ue_ambr.downlink =
ogs_sbi_bitrate_from_string(UeContext->sub_ue_ambr->downlink);
amf_ue->ue_ambr.uplink =
ogs_sbi_bitrate_from_string(UeContext->sub_ue_ambr->uplink);
}
if (UeContext->seaf_data) {
if (UeContext->seaf_data->ng_ksi->tsc != OpenAPI_sc_type_NULL) {
amf_ue->nas.ue.tsc =
(UeContext->seaf_data->ng_ksi->tsc == OpenAPI_sc_type_NATIVE) ? 0 : 1;
amf_ue->nas.ue.ksi = (uint8_t)UeContext->seaf_data->ng_ksi->ksi;
ogs_ascii_to_hex(
UeContext->seaf_data->key_amf->key_val,
strlen(UeContext->seaf_data->key_amf->key_val),
amf_ue->kamf,
sizeof(amf_ue->kamf));
}
}
if (UeContext->_5g_mm_capability) {
ogs_nas_5gmm_capability_t gmm_capability;
gmm_capability = amf_namf_comm_base64_decode_5gmm_capability(
UeContext->_5g_mm_capability);
amf_ue->gmm_capability.lte_positioning_protocol_capability =
(bool)gmm_capability.lte_positioning_protocol_capability;
amf_ue->gmm_capability.ho_attach = (bool)gmm_capability.ho_attach;
amf_ue->gmm_capability.s1_mode = (bool)gmm_capability.s1_mode;
}
if (UeContext->pcf_id) {
/* TODO */
}
/* TODO UeContext->pcfAmPolicyUri */
/* TODO UeContext->pcfUePolicyUri */
if (UeContext->mm_context_list)
amf_namf_comm_decode_ue_mm_context_list(amf_ue, UeContext->mm_context_list);
if (UeContext->session_context_list)
amf_namf_comm_decode_ue_session_context_list(amf_ue, UeContext->session_context_list);
/* TODO ueRadioCapability */
return OGS_OK;
}
static uint8_t gmm_cause_from_access_control(ogs_plmn_id_t *plmn_id)
{
int i;

View File

@ -21,6 +21,7 @@
#define GMM_HANDLER_H
#include "context.h"
#include "namf-handler.h"
#ifdef __cplusplus
extern "C" {
@ -29,13 +30,15 @@ extern "C" {
ogs_nas_5gmm_cause_t gmm_handle_registration_request(amf_ue_t *amf_ue,
ogs_nas_security_header_type_t h, NGAP_ProcedureCode_t ngap_code,
ogs_nas_5gs_registration_request_t *registration_request);
ogs_nas_5gmm_cause_t gmm_handle_registration_update(amf_ue_t *amf_ue,
ogs_nas_5gmm_cause_t gmm_handle_registration_update(
ran_ue_t *ran_ue, amf_ue_t *amf_ue,
ogs_nas_5gs_registration_request_t *registration_request);
ogs_nas_5gmm_cause_t gmm_handle_service_request(amf_ue_t *amf_ue,
ogs_nas_security_header_type_t h, NGAP_ProcedureCode_t ngap_code,
ogs_nas_5gs_service_request_t *service_request);
ogs_nas_5gmm_cause_t gmm_handle_service_update(amf_ue_t *amf_ue,
ogs_nas_5gmm_cause_t gmm_handle_service_update(
ran_ue_t *ran_ue, amf_ue_t *amf_ue,
ogs_nas_5gs_service_request_t *service_request);
int gmm_handle_deregistration_request(amf_ue_t *amf_ue,

View File

@ -27,8 +27,10 @@
#include "nsmf-handler.h"
#include "nudm-handler.h"
#include "npcf-handler.h"
#include "namf-handler.h"
#include "sbi-path.h"
#include "amf-sm.h"
#include "namf-build.h"
#undef OGS_LOG_DOMAIN
#define OGS_LOG_DOMAIN __gmm_log_domain
@ -299,7 +301,7 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e)
AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED) {
int xact_count = amf_sess_xact_count(amf_ue);
amf_sbi_send_release_all_sessions(amf_ue, state);
amf_sbi_send_release_all_sessions(NULL, amf_ue, state);
if (!AMF_SESSION_RELEASE_PENDING(amf_ue) &&
amf_sess_xact_count(amf_ue) == xact_count) {
@ -546,6 +548,59 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e)
END
break;
CASE(OGS_SBI_SERVICE_NAME_NAMF_COMM)
SWITCH(sbi_message->h.resource.component[0])
CASE(OGS_SBI_RESOURCE_NAME_UE_CONTEXTS)
SWITCH(sbi_message->h.resource.component[2])
CASE(OGS_SBI_RESOURCE_NAME_TRANSFER)
if (sbi_message->res_status == OGS_SBI_HTTP_STATUS_OK) {
r = amf_namf_comm_handle_ue_context_transfer_response(sbi_message, amf_ue);
ogs_expect(r == OGS_OK);
}
int xact_count = amf_sess_xact_count(amf_ue);
if (!AMF_UE_HAVE_SUCI(amf_ue)) {
CLEAR_AMF_UE_TIMER(amf_ue->t3570);
r = nas_5gs_send_identity_request(amf_ue);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
break;
}
amf_sbi_send_release_all_sessions(
amf_ue->ran_ue, amf_ue,
AMF_RELEASE_SM_CONTEXT_NO_STATE);
if (!AMF_SESSION_RELEASE_PENDING(amf_ue) &&
amf_sess_xact_count(amf_ue) == xact_count) {
r = amf_ue_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NAUSF_AUTH, NULL,
amf_nausf_auth_build_authenticate,
amf_ue, 0, NULL);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
OGS_FSM_TRAN(s, &gmm_state_authentication);
break;
DEFAULT
ogs_error("Invalid resource name [%s]",
sbi_message->h.resource.component[2]);
ogs_assert_if_reached();
END
break;
DEFAULT
ogs_error("Invalid resource name [%s]",
sbi_message->h.resource.component[0]);
ogs_assert_if_reached();
END
break;
DEFAULT
ogs_error("Invalid service name [%s]", sbi_message->h.service.name);
ogs_assert_if_reached();
@ -829,7 +884,7 @@ void gmm_state_registered(ogs_fsm_t *s, amf_event_t *e)
AMF_NETWORK_INITIATED_EXPLICIT_DE_REGISTERED) {
int xact_count = amf_sess_xact_count(amf_ue);
amf_sbi_send_release_all_sessions(amf_ue, state);
amf_sbi_send_release_all_sessions(NULL, amf_ue, state);
if (!AMF_SESSION_RELEASE_PENDING(amf_ue) &&
amf_sess_xact_count(amf_ue) == xact_count) {
@ -1000,7 +1055,8 @@ void gmm_state_registered(ogs_fsm_t *s, amf_event_t *e)
} else {
amf_sbi_send_release_all_sessions(amf_ue, state);
amf_sbi_send_release_all_sessions(
NULL, amf_ue, state);
if (!AMF_SESSION_RELEASE_PENDING(amf_ue) &&
amf_sess_xact_count(amf_ue) == xact_count) {
@ -1136,6 +1192,9 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e,
amf_sess_t *sess = NULL;
ogs_nas_5gs_message_t *nas_message = NULL;
ogs_nas_security_header_type_t h;
ogs_nas_5gs_registration_request_t *registration_request = NULL;
ogs_nas_5gs_mobile_identity_header_t *mobile_identity_header = NULL;
ogs_nas_5gs_mobile_identity_t *mobile_identity = NULL;
ogs_assert(e);
@ -1194,6 +1253,66 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e,
break;
}
registration_request = &nas_message->gmm.registration_request;
mobile_identity = &registration_request->mobile_identity;
mobile_identity_header =
(ogs_nas_5gs_mobile_identity_header_t *)mobile_identity->buffer;
/* Check if registration is done with GUTI */
if (mobile_identity_header && mobile_identity_header->type ==
OGS_NAS_5GS_MOBILE_IDENTITY_GUTI &&
ogs_nas_5gs_guti_is_valid(&amf_ue->current.guti)) {
/*
* TS 23.502
* 4.2.2.2.2 General Registration
* (Without UDSF Deployment): If the UE's 5G-GUTI was included in the
* Registration Request and the serving AMF has changed since last
* Registration procedure, the new AMF may invoke the
* Namf_Communication_UEContextTransfer service operation on the
* old AMF including the complete Registration Request NAS message,
* which may be integrity protected, as well as the Access Type,
* to request the UE's SUPI and UE Context. See clause 5.2.2.2.2
* for details of this service operation.
*/
int state = e->h.sbi.state;
bool serving_guami = false;
int i;
/* Compare all serving guamis with guami from UE's GUTI */
for (i = 0; i < amf_self()->num_of_served_guami; i++) {
if ((memcmp(&amf_self()->served_guami[i].amf_id,
&amf_ue->current.guti.amf_id,
sizeof(ogs_amf_id_t)) == 0) &&
(memcmp(&amf_self()->served_guami[i].plmn_id,
&amf_ue->current.guti.nas_plmn_id,
OGS_PLMN_ID_LEN) == 0)) {
serving_guami = true;
break;
}
}
if (!serving_guami) {
/* Guami from UE is not this AMF's serving guami - send UEContextTransfer */
ogs_sbi_discovery_option_t *discovery_option = NULL;
discovery_option = ogs_sbi_discovery_option_new();
ogs_assert(discovery_option);
memcpy(discovery_option->target_guami,
amf_ue->guami, sizeof(ogs_guami_t));
int r = amf_ue_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NAMF_COMM, discovery_option,
amf_namf_comm_build_ue_context_transfer,
amf_ue, state, nas_message);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
break;
}
}
if (!AMF_UE_HAVE_SUCI(amf_ue)) {
CLEAR_AMF_UE_TIMER(amf_ue->t3570);
r = nas_5gs_send_identity_request(amf_ue);
@ -1212,7 +1331,7 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e,
CLEAR_NG_CONTEXT(amf_ue);
gmm_cause = gmm_handle_registration_update(
amf_ue, &nas_message->gmm.registration_request);
ran_ue, amf_ue, &nas_message->gmm.registration_request);
if (gmm_cause != OGS_5GMM_CAUSE_REQUEST_ACCEPTED) {
ogs_error("[%s] gmm_handle_registration_update() "
"failed [%d]", amf_ue->suci, gmm_cause);
@ -1271,7 +1390,7 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e,
} else {
amf_sbi_send_release_all_sessions(
amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
ran_ue, amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
if (!AMF_SESSION_RELEASE_PENDING(amf_ue) &&
amf_sess_xact_count(amf_ue) == xact_count) {
@ -1341,7 +1460,7 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e,
CLEAR_NG_CONTEXT(amf_ue);
gmm_cause = gmm_handle_service_update(
amf_ue, &nas_message->gmm.service_request);
ran_ue, amf_ue, &nas_message->gmm.service_request);
if (gmm_cause != OGS_5GMM_CAUSE_REQUEST_ACCEPTED) {
ogs_error("[%s] gmm_handle_service_update() failed [%d]",
amf_ue->suci, gmm_cause);
@ -1392,7 +1511,7 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e,
}
amf_sbi_send_release_all_sessions(
amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
ran_ue, amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
if (!AMF_SESSION_RELEASE_PENDING(amf_ue) &&
amf_sess_xact_count(amf_ue) == xact_count) {
@ -2296,7 +2415,7 @@ void gmm_state_initial_context_setup(ogs_fsm_t *s, amf_event_t *e)
}
amf_sbi_send_release_all_sessions(
amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
ran_ue, amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
if (!AMF_SESSION_RELEASE_PENDING(amf_ue) &&
amf_sess_xact_count(amf_ue) == xact_count) {
@ -2431,7 +2550,7 @@ void gmm_state_exception(ogs_fsm_t *s, amf_event_t *e)
xact_count = amf_sess_xact_count(amf_ue);
amf_sbi_send_release_all_sessions(
amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
amf_ue->ran_ue, amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
if (!AMF_SESSION_RELEASE_PENDING(amf_ue) &&
amf_sess_xact_count(amf_ue) == xact_count) {
@ -2492,7 +2611,7 @@ void gmm_state_exception(ogs_fsm_t *s, amf_event_t *e)
CLEAR_NG_CONTEXT(amf_ue);
gmm_cause = gmm_handle_registration_update(
amf_ue, &nas_message->gmm.registration_request);
ran_ue, amf_ue, &nas_message->gmm.registration_request);
if (gmm_cause != OGS_5GMM_CAUSE_REQUEST_ACCEPTED) {
ogs_error("[%s] gmm_handle_registration_update() "
"failed [%d]", amf_ue->suci, gmm_cause);
@ -2543,7 +2662,7 @@ void gmm_state_exception(ogs_fsm_t *s, amf_event_t *e)
} else {
amf_sbi_send_release_all_sessions(
amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
ran_ue, amf_ue, AMF_RELEASE_SM_CONTEXT_NO_STATE);
if (!AMF_SESSION_RELEASE_PENDING(amf_ue) &&
amf_sess_xact_count(amf_ue) == xact_count) {

View File

@ -40,6 +40,7 @@ libamf_sources = files('''
nnrf-build.c
nnrf-handler.c
namf-build.c
namf-handler.c
sbi-path.c

100
src/amf/namf-build.c Normal file
View File

@ -0,0 +1,100 @@
/*
* 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 "namf-build.h"
static char* ogs_guti_to_string(amf_ue_t *amf_ue)
{
ogs_plmn_id_t plmn_id;
char plmn_id_buff[OGS_PLMNIDSTRLEN];
char *amf_id = NULL;
char *tmsi = NULL;
char *guti = NULL;
memset(&plmn_id, 0, sizeof(plmn_id));
ogs_nas_to_plmn_id(&plmn_id, &amf_ue->current.guti.nas_plmn_id);
amf_id = ogs_amf_id_to_string(&amf_ue->current.guti.amf_id);
tmsi = ogs_uint32_to_0string(*(amf_ue->current.m_tmsi));
guti = ogs_msprintf("5g-guti-%s%s%s",
ogs_plmn_id_to_string(&plmn_id, plmn_id_buff),
amf_id,
tmsi);
/* TS29.518 6.1.3.2.2 Guti pattern (27 or 28 characters):
"5g-guti-[0-9]{5,6}[0-9a-fA-F]{14}" */
ogs_assert(strlen(guti) == (OGS_MAX_5G_GUTI_LEN - 1) ||
(strlen(guti)) == OGS_MAX_5G_GUTI_LEN);
ogs_free(amf_id);
ogs_free(tmsi);
return guti;
}
static char* amf_ue_to_context_id(amf_ue_t *amf_ue)
{
char *ue_context_id = NULL;
if (amf_ue->supi) {
ue_context_id = ogs_strdup(amf_ue->supi);
} else {
ue_context_id = ogs_guti_to_string(amf_ue);
}
return ue_context_id;
}
ogs_sbi_request_t *amf_namf_comm_build_ue_context_transfer(
amf_ue_t *amf_ue, void *data)
{
ogs_sbi_message_t message;
ogs_sbi_request_t *request = NULL;
OpenAPI_ue_context_transfer_req_data_t UeContextTransferReqData;
char *ue_context_id = NULL;
ogs_assert(amf_ue);
ue_context_id = amf_ue_to_context_id(amf_ue);
ogs_assert(ue_context_id);
memset(&UeContextTransferReqData, 0, sizeof(UeContextTransferReqData));
UeContextTransferReqData.access_type = amf_ue->nas.access_type;
UeContextTransferReqData.reason = amf_ue->nas.registration.value;
memset(&message, 0, sizeof(message));
message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST;
message.h.service.name = (char *)OGS_SBI_SERVICE_NAME_NAMF_COMM;
message.h.api.version = (char *)OGS_SBI_API_V1;
message.h.resource.component[0] =
(char *)OGS_SBI_RESOURCE_NAME_UE_CONTEXTS;
message.h.resource.component[1] = ue_context_id;
message.h.resource.component[2] =
(char *)OGS_SBI_RESOURCE_NAME_TRANSFER;
message.UeContextTransferReqData = &UeContextTransferReqData;
request = ogs_sbi_build_request(&message);
ogs_expect(request);
if (ue_context_id)
ogs_free(ue_context_id);
return request;
}

36
src/amf/namf-build.h Normal file
View File

@ -0,0 +1,36 @@
/*
* 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_NAMF_BUILD_H
#define AMF_NAMF_BUILD_H
#ifdef __cplusplus
extern "C" {
#endif
#include "context.h"
ogs_sbi_request_t *amf_namf_comm_build_ue_context_transfer(
amf_ue_t *amf_ue, void *data);
#ifdef __cplusplus
}
#endif
#endif /* AMF_NAMF_BUILD_H */

View File

@ -1079,3 +1079,396 @@ cleanup:
return OGS_OK;
}
static char *amf_namf_comm_base64_encode_ue_security_capability(
ogs_nas_ue_security_capability_t ue_security_capability)
{
char *enc = NULL;
int enc_len = 0;
char num_of_octets =
ue_security_capability.length +
sizeof(ue_security_capability.length) +
sizeof((uint8_t)OGS_NAS_5GS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_TYPE);
/* Security guarantee */
num_of_octets = ogs_min(
num_of_octets, sizeof(ue_security_capability) + 1);
/*
* size [sizeof(ue_security_capability) + 1] is a sum of lengths:
* ue_security_capability (9 octets) +
* type (1 octet)
*/
char security_octets_string[sizeof(ue_security_capability) + 1];
enc_len = ogs_base64_encode_len(num_of_octets);
enc = ogs_malloc(enc_len);
ogs_assert(enc);
memset(enc, 0, sizeof(*enc));
security_octets_string[0] =
(uint8_t)OGS_NAS_5GS_REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_TYPE;
memcpy(security_octets_string + 1, &ue_security_capability, num_of_octets);
ogs_base64_encode(enc , security_octets_string, num_of_octets);
return enc;
}
static char *amf_namf_comm_base64_encode_5gmm_capability(amf_ue_t *amf_ue)
{
ogs_nas_5gmm_capability_t nas_gmm_capability;
int enc_len = 0;
char *enc = NULL;
memset(&nas_gmm_capability, 0, sizeof(nas_gmm_capability));
/* 1 octet is mandatory, n.3 from TS 24.501 V16.12.0, 9.11.3.1 */
nas_gmm_capability.length = 1;
nas_gmm_capability.lte_positioning_protocol_capability =
amf_ue->gmm_capability.lte_positioning_protocol_capability;
nas_gmm_capability.ho_attach = amf_ue->gmm_capability.ho_attach;
nas_gmm_capability.s1_mode = amf_ue->gmm_capability.s1_mode;
uint8_t num_of_octets =
nas_gmm_capability.length +
sizeof(nas_gmm_capability.length) +
sizeof((uint8_t)OGS_NAS_5GS_REGISTRATION_REQUEST_5GMM_CAPABILITY_TYPE);
/* Security guarantee. + 1 stands for 5GMM capability IEI */
num_of_octets = ogs_min(
num_of_octets, sizeof(ogs_nas_5gmm_capability_t) + 1);
char gmm_capability_octets_string[sizeof(ogs_nas_5gmm_capability_t) + 1];
enc_len = ogs_base64_encode_len(num_of_octets);
enc = ogs_malloc(enc_len);
ogs_assert(enc);
memset(enc, 0, sizeof(*enc));
/* Fill the bytes of data */
gmm_capability_octets_string[0] =
(uint8_t)OGS_NAS_5GS_REGISTRATION_REQUEST_5GMM_CAPABILITY_TYPE;
memcpy(gmm_capability_octets_string + 1, &nas_gmm_capability, num_of_octets);
ogs_base64_encode(enc, gmm_capability_octets_string, num_of_octets);
return enc;
}
static OpenAPI_list_t *amf_namf_comm_encode_ue_session_context_list(amf_ue_t *amf_ue)
{
ogs_assert(amf_ue);
amf_sess_t *sess = NULL;
OpenAPI_list_t *PduSessionList = NULL;
OpenAPI_pdu_session_context_t *PduSessionContext = NULL;
OpenAPI_snssai_t *sNSSAI = NULL;
PduSessionList = OpenAPI_list_create();
ogs_assert(PduSessionList);
ogs_list_for_each(&amf_ue->sess_list, sess) {
PduSessionContext = ogs_calloc(1, sizeof(*PduSessionContext));
ogs_assert(PduSessionContext);
sNSSAI = ogs_calloc(1, sizeof(*sNSSAI));
ogs_assert(sNSSAI);
PduSessionContext->pdu_session_id = sess->psi;
PduSessionContext->sm_context_ref = sess->sm_context_ref;
sNSSAI->sst = sess->s_nssai.sst;
sNSSAI->sd = ogs_s_nssai_sd_to_string(sess->s_nssai.sd);
PduSessionContext->s_nssai = sNSSAI;
PduSessionContext->dnn = sess->dnn;
PduSessionContext->access_type = (OpenAPI_access_type_e)amf_ue->nas.access_type;
OpenAPI_list_add(PduSessionList, PduSessionContext);
}
return PduSessionList;
}
static OpenAPI_list_t *amf_namf_comm_encode_ue_mm_context_list(amf_ue_t *amf_ue)
{
OpenAPI_list_t *MmContextList = NULL;
OpenAPI_mm_context_t *MmContext = NULL;
int i;
ogs_assert(amf_ue);
MmContextList = OpenAPI_list_create();
ogs_assert(MmContextList);
MmContext = ogs_malloc(sizeof(*MmContext));
ogs_assert(MmContext);
memset(MmContext, 0, sizeof(*MmContext));
MmContext->access_type = (OpenAPI_access_type_e)amf_ue->nas.access_type;
if ((OpenAPI_ciphering_algorithm_e)amf_ue->selected_enc_algorithm &&
(OpenAPI_integrity_algorithm_e)amf_ue->selected_int_algorithm) {
OpenAPI_nas_security_mode_t *NasSecurityMode;
NasSecurityMode = ogs_calloc(1, sizeof(*NasSecurityMode));
ogs_assert(NasSecurityMode);
NasSecurityMode->ciphering_algorithm =
(OpenAPI_ciphering_algorithm_e)amf_ue->selected_enc_algorithm;
NasSecurityMode->integrity_algorithm =
(OpenAPI_integrity_algorithm_e)amf_ue->selected_int_algorithm;
MmContext->nas_security_mode = NasSecurityMode;
}
if (amf_ue->dl_count > 0) {
MmContext->is_nas_downlink_count = true;
MmContext->nas_downlink_count = amf_ue->dl_count;
}
if (amf_ue->ul_count.i32 > 0) {
MmContext->is_nas_uplink_count = true;
MmContext->nas_uplink_count = amf_ue->ul_count.i32;
}
if (amf_ue->ue_security_capability.length > 0) {
MmContext->ue_security_capability =
amf_namf_comm_base64_encode_ue_security_capability(
amf_ue->ue_security_capability);
}
if (amf_ue->allowed_nssai.num_of_s_nssai) {
OpenAPI_list_t *AllowedNssaiList;
OpenAPI_list_t *NssaiMappingList;
/* This IE shall be present if the source AMF and the target AMF are
* in the same PLMN and if available. When present, this IE shall
* contain the allowed NSSAI for the access type.
*/
AllowedNssaiList = OpenAPI_list_create();
/* This IE shall be present if the source AMF and the target AMF are
* in the same PLMN and if available. When present, this IE shall
* contain the mapping of the allowed NSSAI for the UE.
*/
NssaiMappingList = OpenAPI_list_create();
ogs_assert(AllowedNssaiList);
ogs_assert(NssaiMappingList);
for (i = 0; i < amf_ue->allowed_nssai.num_of_s_nssai; i++) {
OpenAPI_snssai_t *AllowedNssai;
AllowedNssai = ogs_calloc(1, sizeof(*AllowedNssai));
ogs_assert(AllowedNssai);
AllowedNssai->sst = amf_ue->allowed_nssai.s_nssai[i].sst;
AllowedNssai->sd = ogs_s_nssai_sd_to_string(
amf_ue->allowed_nssai.s_nssai[i].sd);
OpenAPI_list_add(AllowedNssaiList, AllowedNssai);
}
for (i = 0; i < amf_ue->allowed_nssai.num_of_s_nssai; i++) {
OpenAPI_nssai_mapping_t *NssaiMapping;
OpenAPI_snssai_t *HSnssai;
OpenAPI_snssai_t *MappedSnssai;
NssaiMapping = ogs_calloc(1, sizeof(*NssaiMapping));
ogs_assert(NssaiMapping);
/* Indicates the S-NSSAI in home PLMN */
HSnssai = ogs_calloc(1, sizeof(*HSnssai));
ogs_assert(HSnssai);
HSnssai->sst =
amf_ue->allowed_nssai.s_nssai[i].mapped_hplmn_sst;
HSnssai->sd =
ogs_s_nssai_sd_to_string(
amf_ue->allowed_nssai.s_nssai[i].mapped_hplmn_sd);
NssaiMapping->h_snssai = HSnssai;
/* Indicates the mapped S-NSSAI in the serving PLMN */
MappedSnssai = ogs_calloc(1, sizeof(*MappedSnssai));
ogs_assert(MappedSnssai);
/* MappedSnssai must be defined, else
"nssaiMappingList" will not convert to json*/
MappedSnssai->sst = 0;
MappedSnssai->sd = ogs_strdup("");
NssaiMapping->mapped_snssai = MappedSnssai;
OpenAPI_list_add(NssaiMappingList, NssaiMapping);
}
MmContext->allowed_nssai = AllowedNssaiList;
MmContext->nssai_mapping_list = NssaiMappingList;
}
OpenAPI_list_add(MmContextList, MmContext);
return MmContextList;
}
int amf_namf_comm_handle_ue_context_transfer_request(
ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg)
{
ogs_sbi_response_t *response = NULL;
ogs_sbi_message_t sendmsg;
amf_ue_t *amf_ue = NULL;
OpenAPI_ambr_t *UeAmbr = NULL;
OpenAPI_list_t *MmContextList = NULL;
OpenAPI_mm_context_t *MmContext = NULL;
OpenAPI_list_t *SessionContextList = NULL;
OpenAPI_pdu_session_context_t *PduSessionContext = NULL;
OpenAPI_lnode_t *node = NULL;
OpenAPI_ue_context_t UeContext;
OpenAPI_seaf_data_t SeafData;
OpenAPI_ng_ksi_t Ng_ksi;
OpenAPI_key_amf_t Key_amf;
OpenAPI_sc_type_e Tsc_type;
OpenAPI_ue_context_transfer_rsp_data_t UeContextTransferRspData;
char *ue_context_id = NULL;
char *encoded_gmm_capability = NULL;
int status = OGS_SBI_HTTP_STATUS_OK;
char hxkamf_string[OGS_KEYSTRLEN(OGS_SHA256_DIGEST_SIZE)];
char *strerror = NULL;
ogs_assert(stream);
ogs_assert(recvmsg);
memset(&UeContextTransferRspData, 0, sizeof(UeContextTransferRspData));
memset(&UeContext, 0, sizeof(UeContext));
UeContextTransferRspData.ue_context = &UeContext;
memset(&sendmsg, 0, sizeof(sendmsg));
sendmsg.UeContextTransferRspData = &UeContextTransferRspData;
ue_context_id = recvmsg->h.resource.component[1];
if (!ue_context_id) {
status = OGS_SBI_HTTP_STATUS_BAD_REQUEST;
strerror = ogs_msprintf("No UE context ID");
goto cleanup;
}
amf_ue = amf_ue_find_by_ue_context_id(ue_context_id);
if (!amf_ue) {
status = OGS_SBI_HTTP_STATUS_NOT_FOUND;
strerror = ogs_msprintf("CONTEXT_NOT_FOUND");
goto cleanup;
}
if (amf_ue->supi) {
UeContext.supi = amf_ue->supi;
if (amf_ue->auth_result !=
OpenAPI_auth_result_AUTHENTICATION_SUCCESS) {
UeContext.is_supi_unauth_ind = true;
UeContext.supi_unauth_ind = amf_ue->auth_result;
}
}
/* TODO UeContext.gpsi_list */
if (amf_ue->pei) {
UeContext.pei = amf_ue->pei;
}
if ((amf_ue->ue_ambr.uplink > 0) || (amf_ue->ue_ambr.downlink > 0)) {
UeAmbr = ogs_malloc(sizeof(*UeAmbr));
ogs_assert(UeAmbr);
memset(UeAmbr, 0, sizeof(*UeAmbr));
if (amf_ue->ue_ambr.uplink > 0)
UeAmbr->uplink = ogs_sbi_bitrate_to_string(
amf_ue->ue_ambr.uplink, OGS_SBI_BITRATE_KBPS);
if (amf_ue->ue_ambr.downlink > 0)
UeAmbr->downlink = ogs_sbi_bitrate_to_string(
amf_ue->ue_ambr.downlink, OGS_SBI_BITRATE_KBPS);
UeContext.sub_ue_ambr = UeAmbr;
}
if ((amf_ue->nas.ue.ksi != 0) && (amf_ue->nas.ue.tsc != 0)) {
memset(&SeafData, 0, sizeof(SeafData));
Tsc_type = (amf_ue->nas.ue.tsc == 0) ?
OpenAPI_sc_type_NATIVE : OpenAPI_sc_type_MAPPED;
memset(&Ng_ksi, 0, sizeof(Ng_ksi));
SeafData.ng_ksi = &Ng_ksi;
Ng_ksi.tsc = Tsc_type;
Ng_ksi.ksi = (int)amf_ue->nas.ue.ksi;
memset(&Key_amf, 0, sizeof(Key_amf));
SeafData.key_amf = &Key_amf;
OpenAPI_key_amf_type_e temp_key_type =
(OpenAPI_key_amf_type_e)OpenAPI_key_amf_type_KAMF;
Key_amf.key_type = temp_key_type;
ogs_hex_to_ascii(amf_ue->kamf, sizeof(amf_ue->kamf),
hxkamf_string, sizeof(hxkamf_string));
Key_amf.key_val = hxkamf_string;
UeContext.seaf_data = &SeafData;
}
encoded_gmm_capability = amf_namf_comm_base64_encode_5gmm_capability(amf_ue);
UeContext._5g_mm_capability = encoded_gmm_capability;
UeContext.pcf_id = amf_ue->sbi.service_type_array[
OGS_SBI_SERVICE_TYPE_NPCF_AM_POLICY_CONTROL].nf_instance->id;
/* TODO UeContext.pcfAmPolicyUri */
/* TODO UeContext.pcfUePolicyUri */
MmContextList = amf_namf_comm_encode_ue_mm_context_list(amf_ue);
UeContext.mm_context_list = MmContextList;
if (recvmsg->UeContextTransferReqData->reason ==
OpenAPI_transfer_reason_MOBI_REG) {
SessionContextList = amf_namf_comm_encode_ue_session_context_list(amf_ue);
UeContext.session_context_list = SessionContextList;
}
/* TODO ueRadioCapability */
response = ogs_sbi_build_response(&sendmsg, status);
ogs_assert(response);
ogs_assert(true == ogs_sbi_server_send_response(stream, response));
if (encoded_gmm_capability)
ogs_free(encoded_gmm_capability);
if (UeAmbr)
OpenAPI_ambr_free(UeAmbr);
if (SessionContextList) {
OpenAPI_list_for_each(SessionContextList, node) {
PduSessionContext = node->data;
OpenAPI_pdu_session_context_free(PduSessionContext);
}
OpenAPI_list_free(SessionContextList);
}
if (MmContextList) {
OpenAPI_list_for_each(MmContextList, node) {
MmContext = node->data;
OpenAPI_mm_context_free(MmContext);
}
OpenAPI_list_free(MmContextList);
}
return OGS_OK;
cleanup:
ogs_assert(strerror);
ogs_error("%s", strerror);
ogs_assert(true ==
ogs_sbi_server_send_error(stream, status, NULL, strerror, NULL));
ogs_free(strerror);
return OGS_ERROR;
}

View File

@ -34,6 +34,10 @@ int amf_namf_callback_handle_dereg_notify(
ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg);
int amf_namf_callback_handle_sdm_data_change_notify(
ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg);
int amf_namf_comm_handle_ue_context_transfer_request(
ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg);
int amf_namf_comm_handle_ue_context_transfer_response(
ogs_sbi_message_t *recvmsg, amf_ue_t *amf_ue);
#ifdef __cplusplus
}

View File

@ -1018,7 +1018,7 @@ void ngap_handle_initial_context_setup_response(
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context,
sess, AMF_UPDATE_SM_CONTEXT_ACTIVATED, &param);
ran_ue, sess, AMF_UPDATE_SM_CONTEXT_ACTIVATED, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -1248,7 +1248,7 @@ void ngap_handle_initial_context_setup_failure(
amf_ue->deactivation.cause = NGAP_CauseNas_normal_release;
amf_sbi_send_deactivate_all_sessions(
amf_ue, AMF_UPDATE_SM_CONTEXT_DEACTIVATED,
ran_ue, amf_ue, AMF_UPDATE_SM_CONTEXT_DEACTIVATED,
Cause->present, (int)Cause->choice.radioNetwork);
new_xact_count = amf_sess_xact_count(amf_ue);
@ -1552,7 +1552,7 @@ void ngap_handle_ue_context_release_request(
if (!PDUSessionList) {
amf_sbi_send_deactivate_all_sessions(
amf_ue, AMF_UPDATE_SM_CONTEXT_DEACTIVATED,
ran_ue, amf_ue, AMF_UPDATE_SM_CONTEXT_DEACTIVATED,
Cause->present, (int)Cause->choice.radioNetwork);
} else {
for (i = 0; i < PDUSessionList->list.count; i++) {
@ -1584,7 +1584,7 @@ void ngap_handle_ue_context_release_request(
PDUSessionItem->pDUSessionID);
if (SESSION_CONTEXT_IN_SMF(sess)) {
amf_sbi_send_deactivate_session(
sess, AMF_UPDATE_SM_CONTEXT_DEACTIVATED,
ran_ue, sess, AMF_UPDATE_SM_CONTEXT_DEACTIVATED,
Cause->present, (int)Cause->choice.radioNetwork);
}
}
@ -2002,7 +2002,7 @@ void ngap_handle_pdu_session_resource_setup_response(
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context,
sess, AMF_UPDATE_SM_CONTEXT_ACTIVATED, &param);
ran_ue, sess, AMF_UPDATE_SM_CONTEXT_ACTIVATED, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -2128,7 +2128,7 @@ void ngap_handle_pdu_session_resource_setup_response(
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context,
sess, AMF_UPDATE_SM_CONTEXT_SETUP_FAIL, &param);
ran_ue, sess, AMF_UPDATE_SM_CONTEXT_SETUP_FAIL, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -2321,7 +2321,7 @@ void ngap_handle_pdu_session_resource_modify_response(
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context,
sess, AMF_UPDATE_SM_CONTEXT_MODIFIED, &param);
ran_ue, sess, AMF_UPDATE_SM_CONTEXT_MODIFIED, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -2508,7 +2508,7 @@ void ngap_handle_pdu_session_resource_release_response(
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context,
sess, AMF_UPDATE_SM_CONTEXT_N2_RELEASED, &param);
ran_ue, sess, AMF_UPDATE_SM_CONTEXT_N2_RELEASED, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -2977,7 +2977,8 @@ void ngap_handle_path_switch_request(
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context,
sess, AMF_UPDATE_SM_CONTEXT_PATH_SWITCH_REQUEST, &param);
ran_ue, sess,
AMF_UPDATE_SM_CONTEXT_PATH_SWITCH_REQUEST, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -3366,7 +3367,8 @@ void ngap_handle_handover_required(
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context,
sess, AMF_UPDATE_SM_CONTEXT_HANDOVER_REQUIRED, &param);
source_ue, sess,
AMF_UPDATE_SM_CONTEXT_HANDOVER_REQUIRED, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -3607,7 +3609,8 @@ void ngap_handle_handover_request_ack(
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context,
sess, AMF_UPDATE_SM_CONTEXT_HANDOVER_REQ_ACK, &param);
target_ue, sess,
AMF_UPDATE_SM_CONTEXT_HANDOVER_REQ_ACK, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -3879,7 +3882,7 @@ void ngap_handle_handover_cancel(
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context,
sess, AMF_UPDATE_SM_CONTEXT_HANDOVER_CANCEL, &param);
source_ue, sess, AMF_UPDATE_SM_CONTEXT_HANDOVER_CANCEL, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
@ -4188,7 +4191,7 @@ void ngap_handle_handover_notification(
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context,
sess, AMF_UPDATE_SM_CONTEXT_HANDOVER_NOTIFY, &param);
source_ue, sess, AMF_UPDATE_SM_CONTEXT_HANDOVER_NOTIFY, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
@ -4604,7 +4607,7 @@ void ngap_handle_ng_reset(
old_xact_count = amf_sess_xact_count(amf_ue);
amf_sbi_send_deactivate_all_sessions(
amf_ue, AMF_REMOVE_S1_CONTEXT_BY_RESET_PARTIAL,
ran_ue, amf_ue, AMF_REMOVE_S1_CONTEXT_BY_RESET_PARTIAL,
NGAP_Cause_PR_radioNetwork,
NGAP_CauseRadioNetwork_failure_in_radio_interface_procedure);

View File

@ -121,7 +121,7 @@ int amf_nnssf_nsselection_handle_get(
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, discovery_option,
amf_nsmf_pdusession_build_create_sm_context,
sess, AMF_CREATE_SM_CONTEXT_NO_STATE, &param);
ran_ue, sess, AMF_CREATE_SM_CONTEXT_NO_STATE, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else {
@ -163,7 +163,8 @@ int amf_nnssf_nsselection_handle_get(
ogs_freeaddrinfo(addr6);
r = amf_sess_sbi_discover_by_nsi(
sess, OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, discovery_option);
ran_ue, sess,
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, discovery_option);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}

View File

@ -635,7 +635,7 @@ int amf_nsmf_pdusession_handle_update_sm_context(
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_create_sm_context,
sess, AMF_CREATE_SM_CONTEXT_NO_STATE, NULL);
ran_ue, sess, AMF_CREATE_SM_CONTEXT_NO_STATE, NULL);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else {

View File

@ -36,6 +36,7 @@ int amf_sbi_open(void)
ogs_sbi_nf_instance_build_default(nf_instance);
ogs_sbi_nf_instance_add_allowed_nf_type(nf_instance, OpenAPI_nf_type_SCP);
ogs_sbi_nf_instance_add_allowed_nf_type(nf_instance, OpenAPI_nf_type_SMF);
ogs_sbi_nf_instance_add_allowed_nf_type(nf_instance, OpenAPI_nf_type_AMF);
/* Build NF service information. It will be transmitted to NRF. */
if (ogs_sbi_nf_service_is_available(OGS_SBI_SERVICE_NAME_NAMF_COMM)) {
@ -45,6 +46,7 @@ int amf_sbi_open(void)
ogs_sbi_nf_service_add_version(
service, OGS_SBI_API_V1, OGS_SBI_API_V1_0_0, NULL);
ogs_sbi_nf_service_add_allowed_nf_type(service, OpenAPI_nf_type_SMF);
ogs_sbi_nf_service_add_allowed_nf_type(service, OpenAPI_nf_type_AMF);
}
/* Initialize NRF NF Instance */
@ -156,30 +158,24 @@ int amf_sess_sbi_discover_and_send(
ogs_sbi_service_type_e service_type,
ogs_sbi_discovery_option_t *discovery_option,
ogs_sbi_request_t *(*build)(amf_sess_t *sess, void *data),
amf_sess_t *sess, int state, void *data)
ran_ue_t *ran_ue, amf_sess_t *sess, int state, void *data)
{
int r;
int rv;
ogs_sbi_xact_t *xact = NULL;
amf_ue_t *amf_ue = NULL;
ogs_assert(service_type);
ogs_assert(sess);
ogs_assert(build);
amf_ue = amf_ue_cycle(sess->amf_ue);
if (!amf_ue) {
ogs_error("UE(amf_ue) Context has already been removed");
return OGS_NOTFOUND;
}
sess->ran_ue = ran_ue_cycle(amf_ue->ran_ue);
if (!sess->ran_ue) {
ogs_error("[%s] RAN-NG Context has already been removed",
amf_ue->supi);
return OGS_NOTFOUND;
}
if (ran_ue) {
sess->ran_ue = ran_ue_cycle(ran_ue);
if (!sess->ran_ue) {
ogs_error("NG context has already been removed");
return OGS_NOTFOUND;
}
} else
sess->ran_ue = NULL;
xact = ogs_sbi_xact_add(
&sess->sbi, service_type, discovery_option,
@ -219,6 +215,7 @@ static int client_discover_cb(
OpenAPI_nf_type_e requester_nf_type = OpenAPI_nf_type_NULL;
ogs_sbi_discovery_option_t *discovery_option = NULL;
amf_ue_t *amf_ue = NULL;
ran_ue_t *ran_ue = NULL;
amf_sess_t *sess = NULL;
xact = data;
@ -251,14 +248,30 @@ static int client_discover_cb(
}
ogs_assert(sess->sbi.type == OGS_SBI_OBJ_SESS_TYPE);
amf_ue = sess->amf_ue;
ogs_assert(amf_ue);
amf_ue = amf_ue_cycle(sess->amf_ue);
if (!amf_ue) {
ogs_error("UE(amf-ue) context has already been removed");
ogs_sbi_xact_remove(xact);
if (response)
ogs_sbi_response_free(response);
return OGS_ERROR;
}
ran_ue = ran_ue_cycle(sess->ran_ue);
if (!ran_ue) {
ogs_error("[%s] NG context has already been removed", amf_ue->supi);
ogs_sbi_xact_remove(xact);
if (response)
ogs_sbi_response_free(response);
return OGS_ERROR;
}
if (status != OGS_OK) {
ogs_log_message(
status == OGS_DONE ? OGS_LOG_DEBUG : OGS_LOG_WARN, 0,
"client_discover_cb() failed [%d]", status);
ogs_sbi_xact_remove(xact);
if (response)
ogs_sbi_response_free(response);
return OGS_ERROR;
}
@ -267,7 +280,7 @@ static int client_discover_cb(
rv = ogs_sbi_parse_response(&message, response);
if (rv != OGS_OK) {
ogs_error("cannot parse HTTP response");
r = nas_5gs_send_back_gsm_message(sess->ran_ue, sess,
r = nas_5gs_send_back_gsm_message(ran_ue, sess,
OGS_5GMM_CAUSE_PAYLOAD_WAS_NOT_FORWARDED, AMF_NAS_BACKOFF_TIME);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -277,7 +290,7 @@ static int client_discover_cb(
if (message.res_status != OGS_SBI_HTTP_STATUS_OK) {
ogs_error("NF-Discover failed [%d]", message.res_status);
r = nas_5gs_send_back_gsm_message(sess->ran_ue, sess,
r = nas_5gs_send_back_gsm_message(ran_ue, sess,
OGS_5GMM_CAUSE_PAYLOAD_WAS_NOT_FORWARDED, AMF_NAS_BACKOFF_TIME);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -287,7 +300,7 @@ static int client_discover_cb(
if (!message.SearchResult) {
ogs_error("No SearchResult");
r = nas_5gs_send_back_gsm_message(sess->ran_ue, sess,
r = nas_5gs_send_back_gsm_message(ran_ue, sess,
OGS_5GMM_CAUSE_PAYLOAD_WAS_NOT_FORWARDED, AMF_NAS_BACKOFF_TIME);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -304,7 +317,7 @@ static int client_discover_cb(
ogs_error("[%s:%d] (NF discover) No [%s]",
amf_ue->supi, sess->psi,
ogs_sbi_service_type_to_name(service_type));
r = nas_5gs_send_back_gsm_message(sess->ran_ue, sess,
r = nas_5gs_send_back_gsm_message(ran_ue, sess,
OGS_5GMM_CAUSE_PAYLOAD_WAS_NOT_FORWARDED,
AMF_NAS_BACKOFF_TIME);
ogs_expect(r == OGS_OK);
@ -316,7 +329,7 @@ static int client_discover_cb(
r = amf_sess_sbi_discover_and_send(
service_type, NULL,
amf_nsmf_pdusession_build_create_sm_context,
sess, AMF_CREATE_SM_CONTEXT_NO_STATE, NULL);
ran_ue, sess, AMF_CREATE_SM_CONTEXT_NO_STATE, NULL);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -337,15 +350,13 @@ cleanup:
}
int amf_sess_sbi_discover_by_nsi(
amf_sess_t *sess,
ran_ue_t *ran_ue, amf_sess_t *sess,
ogs_sbi_service_type_e service_type,
ogs_sbi_discovery_option_t *discovery_option)
{
ogs_sbi_xact_t *xact = NULL;
ogs_sbi_client_t *client = NULL;
amf_ue_t *amf_ue = NULL;
ogs_assert(sess);
client = sess->nssf.nrf.client;
ogs_assert(client);
@ -354,18 +365,14 @@ int amf_sess_sbi_discover_by_nsi(
ogs_warn("Try to discover [%s]",
ogs_sbi_service_type_to_name(service_type));
amf_ue = amf_ue_cycle(sess->amf_ue);
if (!amf_ue) {
ogs_error("UE(amf_ue) Context has already been removed");
return OGS_NOTFOUND;
}
sess->ran_ue = ran_ue_cycle(amf_ue->ran_ue);
if (!sess->ran_ue) {
ogs_error("[%s] RAN-NG Context has already been removed",
amf_ue->supi);
return OGS_NOTFOUND;
}
if (ran_ue) {
sess->ran_ue = ran_ue_cycle(ran_ue);
if (!sess->ran_ue) {
ogs_error("NG context has already been removed");
return OGS_NOTFOUND;
}
} else
sess->ran_ue = NULL;
xact = ogs_sbi_xact_add(
&sess->sbi, service_type, discovery_option, NULL, NULL, NULL);
@ -386,7 +393,8 @@ int amf_sess_sbi_discover_by_nsi(
client, client_discover_cb, xact->request, xact) == true ? OGS_OK : OGS_ERROR;
}
void amf_sbi_send_activating_session(amf_sess_t *sess, int state)
void amf_sbi_send_activating_session(
ran_ue_t *ran_ue, amf_sess_t *sess, int state)
{
amf_nsmf_pdusession_sm_context_param_t param;
int r;
@ -398,13 +406,14 @@ void amf_sbi_send_activating_session(amf_sess_t *sess, int state)
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context, sess, state, &param);
amf_nsmf_pdusession_build_update_sm_context,
ran_ue, sess, state, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
void amf_sbi_send_deactivate_session(
amf_sess_t *sess, int state, int group, int cause)
ran_ue_t *ran_ue, amf_sess_t *sess, int state, int group, int cause)
{
amf_nsmf_pdusession_sm_context_param_t param;
int r;
@ -420,13 +429,14 @@ void amf_sbi_send_deactivate_session(
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_update_sm_context, sess, state, &param);
amf_nsmf_pdusession_build_update_sm_context,
ran_ue, sess, state, &param);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
}
void amf_sbi_send_deactivate_all_sessions(
amf_ue_t *amf_ue, int state, int group, int cause)
ran_ue_t *ran_ue, amf_ue_t *amf_ue, int state, int group, int cause)
{
amf_sess_t *sess = NULL;
@ -434,7 +444,7 @@ void amf_sbi_send_deactivate_all_sessions(
ogs_list_for_each(&amf_ue->sess_list, sess) {
if (SESSION_CONTEXT_IN_SMF(sess))
amf_sbi_send_deactivate_session(sess, state, group, cause);
amf_sbi_send_deactivate_session(ran_ue, sess, state, group, cause);
}
}
@ -446,13 +456,13 @@ void amf_sbi_send_deactivate_all_ue_in_gnb(amf_gnb_t *gnb, int state)
ogs_list_for_each_safe(&gnb->ran_ue_list, ran_ue_next, ran_ue) {
int old_xact_count = 0, new_xact_count = 0;
amf_ue = ran_ue->amf_ue;
amf_ue = amf_ue_cycle(ran_ue->amf_ue);
if (amf_ue) {
old_xact_count = amf_sess_xact_count(amf_ue);
amf_sbi_send_deactivate_all_sessions(
amf_ue, state, NGAP_Cause_PR_radioNetwork,
ran_ue, amf_ue, state, NGAP_Cause_PR_radioNetwork,
NGAP_CauseRadioNetwork_failure_in_radio_interface_procedure);
new_xact_count = amf_sess_xact_count(amf_ue);
@ -480,7 +490,8 @@ void amf_sbi_send_deactivate_all_ue_in_gnb(amf_gnb_t *gnb, int state)
}
}
void amf_sbi_send_release_session(amf_sess_t *sess, int state)
void amf_sbi_send_release_session(
ran_ue_t *ran_ue, amf_sess_t *sess, int state)
{
int r;
@ -488,7 +499,8 @@ void amf_sbi_send_release_session(amf_sess_t *sess, int state)
r = amf_sess_sbi_discover_and_send(
OGS_SBI_SERVICE_TYPE_NSMF_PDUSESSION, NULL,
amf_nsmf_pdusession_build_release_sm_context, sess, state, NULL);
amf_nsmf_pdusession_build_release_sm_context,
ran_ue, sess, state, NULL);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
@ -496,7 +508,8 @@ void amf_sbi_send_release_session(amf_sess_t *sess, int state)
CLEAR_SM_CONTEXT_REF(sess);
}
void amf_sbi_send_release_all_sessions(amf_ue_t *amf_ue, int state)
void amf_sbi_send_release_all_sessions(
ran_ue_t *ran_ue, amf_ue_t *amf_ue, int state)
{
amf_sess_t *sess = NULL;
@ -504,7 +517,7 @@ void amf_sbi_send_release_all_sessions(amf_ue_t *amf_ue, int state)
ogs_list_for_each(&amf_ue->sess_list, sess) {
if (SESSION_CONTEXT_IN_SMF(sess))
amf_sbi_send_release_session(sess, state);
amf_sbi_send_release_session(ran_ue, sess, state);
}
}

View File

@ -74,23 +74,26 @@ int amf_sess_sbi_discover_and_send(
ogs_sbi_service_type_e service_type,
ogs_sbi_discovery_option_t *discovery_option,
ogs_sbi_request_t *(*build)(amf_sess_t *sess, void *data),
amf_sess_t *sess, int state, void *data);
ran_ue_t *ran_ue, amf_sess_t *sess, int state, void *data);
int amf_sess_sbi_discover_by_nsi(
amf_sess_t *sess,
ran_ue_t *ran_ue, amf_sess_t *sess,
ogs_sbi_service_type_e service_type,
ogs_sbi_discovery_option_t *discovery_option);
void amf_sbi_send_activating_session(amf_sess_t *sess, int state);
void amf_sbi_send_activating_session(
ran_ue_t *ran_ue, amf_sess_t *sess, int state);
void amf_sbi_send_deactivate_session(
amf_sess_t *sess, int state, int group, int cause);
ran_ue_t *ran_ue, amf_sess_t *sess, int state, int group, int cause);
void amf_sbi_send_deactivate_all_sessions(
amf_ue_t *amf_ue, int state, int group, int cause);
ran_ue_t *ran_ue, amf_ue_t *amf_ue, int state, int group, int cause);
void amf_sbi_send_deactivate_all_ue_in_gnb(amf_gnb_t *gnb, int state);
void amf_sbi_send_release_session(amf_sess_t *sess, int state);
void amf_sbi_send_release_all_sessions(amf_ue_t *amf_ue, int state);
void amf_sbi_send_release_session(
ran_ue_t *ran_ue, amf_sess_t *sess, int state);
void amf_sbi_send_release_all_sessions(
ran_ue_t *ran_ue, amf_ue_t *amf_ue, int state);
bool amf_sbi_send_n1_n2_failure_notify(
amf_sess_t *sess, OpenAPI_n1_n2_message_transfer_cause_e cause);

View File

@ -236,13 +236,17 @@ int esm_handle_information_response(mme_sess_t *sess,
mme_csmap_t *csmap = mme_csmap_find_by_tai(&mme_ue->tai);
mme_ue->csmap = csmap;
if (csmap) {
ogs_assert(OGS_OK ==
sgsap_send_location_update_request(mme_ue));
} else {
if (!csmap ||
mme_ue->network_access_mode ==
OGS_NETWORK_ACCESS_MODE_ONLY_PACKET ||
mme_ue->nas_eps.attach.value ==
OGS_NAS_ATTACH_TYPE_EPS_ATTACH) {
r = nas_eps_send_attach_accept(mme_ue);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else {
ogs_assert(OGS_OK ==
sgsap_send_location_update_request(mme_ue));
}
} else {
ogs_assert(OGS_OK ==

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -254,6 +254,7 @@ int mme_gtp_send_create_session_request(mme_sess_t *sess, int create_action)
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_CREATE_SESSION_REQUEST_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sgw_ue->sgw_s11_teid;
pkbuf = mme_s11_build_create_session_request(h.type, sess, create_action);
@ -293,6 +294,7 @@ int mme_gtp_send_modify_bearer_request(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sgw_ue->sgw_s11_teid;
pkbuf = mme_s11_build_modify_bearer_request(h.type, mme_ue, uli_presence);
@ -332,6 +334,7 @@ int mme_gtp_send_delete_session_request(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_DELETE_SESSION_REQUEST_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sgw_ue->sgw_s11_teid;
s11buf = mme_s11_build_delete_session_request(h.type, sess, action);
@ -400,6 +403,7 @@ int mme_gtp_send_create_bearer_response(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sgw_ue->sgw_s11_teid;
pkbuf = mme_s11_build_create_bearer_response(h.type, bearer, cause_value);
@ -445,6 +449,7 @@ int mme_gtp_send_update_bearer_response(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sgw_ue->sgw_s11_teid;
pkbuf = mme_s11_build_update_bearer_response(h.type, bearer, cause_value);
@ -490,6 +495,7 @@ int mme_gtp_send_delete_bearer_response(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sgw_ue->sgw_s11_teid;
pkbuf = mme_s11_build_delete_bearer_response(h.type, bearer, cause_value);
@ -525,6 +531,7 @@ int mme_gtp_send_release_access_bearers_request(mme_ue_t *mme_ue, int action)
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_RELEASE_ACCESS_BEARERS_REQUEST_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sgw_ue->sgw_s11_teid;
pkbuf = mme_s11_build_release_access_bearers_request(h.type);
@ -622,6 +629,7 @@ int mme_gtp_send_downlink_data_notification_ack(
/* Build Downlink data notification ack */
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sgw_ue->sgw_s11_teid;
s11buf = mme_s11_build_downlink_data_notification_ack(h.type, cause_value);
@ -657,6 +665,7 @@ int mme_gtp_send_create_indirect_data_forwarding_tunnel_request(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sgw_ue->sgw_s11_teid;
pkbuf = mme_s11_build_create_indirect_data_forwarding_tunnel_request(
@ -696,6 +705,7 @@ int mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sgw_ue->sgw_s11_teid;
pkbuf = ogs_pkbuf_alloc(NULL, OGS_TLV_MAX_HEADROOM);
@ -738,6 +748,7 @@ int mme_gtp_send_bearer_resource_command(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_BEARER_RESOURCE_COMMAND_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sgw_ue->sgw_s11_teid;
pkbuf = mme_s11_build_bearer_resource_command(h.type, bearer, nas_message);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -427,17 +427,20 @@ void mme_s11_handle_create_session_response(
mme_csmap_t *csmap = mme_csmap_find_by_tai(&mme_ue->tai);
mme_ue->csmap = csmap;
if (csmap) {
ogs_assert(OGS_PDU_SESSION_TYPE_IS_VALID(
session->paa.session_type));
ogs_assert(OGS_OK ==
sgsap_send_location_update_request(mme_ue));
} else {
if (!csmap ||
mme_ue->network_access_mode ==
OGS_NETWORK_ACCESS_MODE_ONLY_PACKET ||
mme_ue->nas_eps.attach.value ==
OGS_NAS_ATTACH_TYPE_EPS_ATTACH) {
ogs_assert(OGS_PDU_SESSION_TYPE_IS_VALID(
session->paa.session_type));
r = nas_eps_send_attach_accept(mme_ue);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
} else {
ogs_assert(OGS_PDU_SESSION_TYPE_IS_VALID(
session->paa.session_type));
ogs_assert(OGS_OK == sgsap_send_location_update_request(mme_ue));
}
} else if (create_action == OGS_GTP_CREATE_IN_TRACKING_AREA_UPDATE) {
@ -820,7 +823,9 @@ void mme_s11_handle_create_bearer_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp2_send_error_message(xact, sgw_ue ? sgw_ue->sgw_s11_teid : 0,
ogs_gtp2_send_error_message(xact,
sgw_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgw_ue ? sgw_ue->sgw_s11_teid : 0,
OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -856,7 +861,9 @@ void mme_s11_handle_create_bearer_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp2_send_error_message(xact, sgw_ue ? sgw_ue->sgw_s11_teid : 0,
ogs_gtp2_send_error_message(xact,
sgw_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgw_ue ? sgw_ue->sgw_s11_teid : 0,
OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -1012,7 +1019,9 @@ void mme_s11_handle_update_bearer_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp2_send_error_message(xact, sgw_ue ? sgw_ue->sgw_s11_teid : 0,
ogs_gtp2_send_error_message(xact,
sgw_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgw_ue ? sgw_ue->sgw_s11_teid : 0,
OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -1183,7 +1192,9 @@ void mme_s11_handle_delete_bearer_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp2_send_error_message(xact, sgw_ue ? sgw_ue->sgw_s11_teid : 0,
ogs_gtp2_send_error_message(xact,
sgw_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgw_ue ? sgw_ue->sgw_s11_teid : 0,
OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE,
OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND);
return;
@ -1440,7 +1451,9 @@ void mme_s11_handle_downlink_data_notification(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp2_send_error_message(xact, sgw_ue ? sgw_ue->sgw_s11_teid : 0,
ogs_gtp2_send_error_message(xact,
sgw_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgw_ue ? sgw_ue->sgw_s11_teid : 0,
OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_ACKNOWLEDGE_TYPE,
OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND);
return;

View File

@ -210,11 +210,9 @@ void sgsap_handle_location_update_reject(mme_vlr_t *vlr, ogs_pkbuf_t *pkbuf)
ogs_plmn_id_hexdump(&lai->nas_plmn_id), lai->lac);
}
r = nas_eps_send_attach_reject(mme_ue->enb_ue, mme_ue,
emm_cause, OGS_NAS_ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
r = nas_eps_send_attach_accept(mme_ue);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
mme_send_delete_session_or_mme_ue_context_release(mme_ue);
return;

View File

@ -830,6 +830,13 @@ bool nrf_nnrf_handle_nf_discover(
&discovery_option->tai.plmn_id),
discovery_option->tai.tac.v);
}
if (discovery_option->target_guami) {
ogs_debug("guami[PLMN_ID:%06x,AMF_ID:%x]",
ogs_plmn_id_hexdump(
&discovery_option->target_guami->plmn_id),
ogs_amf_id_hexdump(
&discovery_option->target_guami->amf_id));
}
if (discovery_option->num_of_target_plmn_list) {
for (i = 0; i < discovery_option->num_of_target_plmn_list; i++)
ogs_debug("[%d] target-plmn-list[MCC:%03d,MNC:%03d]", i,

View File

@ -225,6 +225,9 @@ static int request_handler(ogs_sbi_request_t *request, void *data)
} else if (!strcasecmp(key, OGS_SBI_CUSTOM_DISCOVERY_SNSSAIS)) {
if (val)
ogs_sbi_discovery_option_parse_snssais(discovery_option, val);
} else if (!strcasecmp(key, OGS_SBI_CUSTOM_DISCOVERY_GUAMI)) {
if (val)
ogs_sbi_discovery_option_parse_guami(discovery_option, val);
} else if (!strcasecmp(key, OGS_SBI_CUSTOM_DISCOVERY_DNN)) {
ogs_sbi_discovery_option_set_dnn(discovery_option, val);
} else if (!strcasecmp(key, OGS_SBI_CUSTOM_DISCOVERY_TAI)) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -182,6 +182,7 @@ int sgwc_gtp_send_create_session_response(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sgwc_ue->mme_s11_teid;
pkbuf = sgwc_s11_build_create_session_response(h.type, sess);
@ -229,6 +230,7 @@ int sgwc_gtp_send_downlink_data_notification(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_DOWNLINK_DATA_NOTIFICATION_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sgwc_ue->mme_s11_teid;
pkbuf = sgwc_s11_build_downlink_data_notification(cause_value, bearer);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -222,6 +222,7 @@ int sgwc_pfcp_send_bearer_to_modify_list(
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->sgwu_sxa_seid;
sxabuf = sgwc_sxa_build_bearer_to_modify_list(h.type, sess, xact);
@ -302,6 +303,7 @@ int sgwc_pfcp_send_session_establishment_request(
* over N4 towards another SMF or another PFCP entity in the SMF
* as specified in clause 5.22.2 and clause 5.22.3.
*/
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->sgwu_sxa_seid;
sxabuf = sgwc_sxa_build_session_establishment_request(h.type, sess);
@ -389,6 +391,7 @@ int sgwc_pfcp_send_bearer_modification_request(
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->sgwu_sxa_seid;
sxabuf = sgwc_sxa_build_bearer_to_modify_list(h.type, sess, xact);
@ -437,6 +440,7 @@ int sgwc_pfcp_send_session_deletion_request(
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_DELETION_REQUEST_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->sgwu_sxa_seid;
sxabuf = sgwc_sxa_build_session_deletion_request(h.type, sess);
@ -466,6 +470,7 @@ int sgwc_pfcp_send_session_report_response(
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->sgwu_sxa_seid;
sxabuf = ogs_pfcp_build_session_report_response(h.type, cause);

View File

@ -356,10 +356,6 @@ void sgwc_pfcp_state_associated(ogs_fsm_t *s, sgwc_event_t *e)
}
break;
case SGWC_EVT_SXA_NO_HEARTBEAT:
/* 'node' context was removed in ogs_pfcp_xact_delete(xact)
* So, we should not use PFCP node here */
ogs_warn("No Heartbeat from SGW-U [%s]:%d",
OGS_ADDR(addr, buf), OGS_PORT(addr));
OGS_FSM_TRAN(s, sgwc_pfcp_state_will_associate);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -173,8 +173,9 @@ void sgwc_s11_handle_create_session_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
@ -214,8 +215,9 @@ void sgwc_s11_handle_create_session_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
@ -262,8 +264,9 @@ void sgwc_s11_handle_create_session_request(
/* Check if selected SGW-U is associated with SGW-C */
ogs_assert(sess->pfcp_node);
if (!OGS_FSM_CHECK(&sess->pfcp_node->sm, sgwc_pfcp_state_associated)) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_REMOTE_PEER_NOT_RESPONDING);
return;
@ -423,8 +426,9 @@ void sgwc_s11_handle_modify_bearer_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -531,8 +535,9 @@ void sgwc_s11_handle_modify_bearer_request(
if (i == 0) {
ogs_error("No Bearer");
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -609,8 +614,9 @@ void sgwc_s11_handle_delete_session_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
@ -629,8 +635,9 @@ void sgwc_s11_handle_delete_session_request(
indication->operation_indication == 1 &&
indication->scope_indication == 1) {
ogs_error("Invalid Indication");
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_INVALID_MESSAGE_FORMAT);
return;
@ -656,6 +663,7 @@ void sgwc_s11_handle_delete_session_request(
} else {
message->h.type = OGS_GTP2_DELETE_SESSION_REQUEST_TYPE;
message->h.teid_presence = OGS_GTP2_TEID_PRESENCE;
message->h.teid = sess->pgw_s5c_teid;
gtpbuf = ogs_gtp2_build_msg(message);
@ -762,7 +770,9 @@ void sgwc_s11_handle_create_bearer_response(
sgwc_pfcp_send_bearer_modification_request(
bearer, NULL, NULL,
OGS_PFCP_MODIFY_UL_ONLY|OGS_PFCP_MODIFY_REMOVE));
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
ogs_gtp2_send_error_message(s5c_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -781,7 +791,9 @@ void sgwc_s11_handle_create_bearer_response(
sgwc_pfcp_send_bearer_modification_request(
bearer, NULL, NULL,
OGS_PFCP_MODIFY_UL_ONLY|OGS_PFCP_MODIFY_REMOVE));
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
ogs_gtp2_send_error_message(s5c_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -915,7 +927,9 @@ void sgwc_s11_handle_update_bearer_response(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
ogs_gtp2_send_error_message(s5c_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -930,7 +944,9 @@ void sgwc_s11_handle_update_bearer_response(
cause_value = cause->value;
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("GTP Bearer Cause [VALUE:%d]", cause_value);
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
ogs_gtp2_send_error_message(s5c_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -940,7 +956,9 @@ void sgwc_s11_handle_update_bearer_response(
cause_value = cause->value;
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("GTP Cause [Value:%d]", cause_value);
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
ogs_gtp2_send_error_message(s5c_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -957,6 +975,7 @@ void sgwc_s11_handle_update_bearer_response(
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
message->h.type = OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE;
message->h.teid_presence = OGS_GTP2_TEID_PRESENCE;
message->h.teid = sess->pgw_s5c_teid;
pkbuf = ogs_gtp2_build_msg(message);
@ -1128,8 +1147,9 @@ void sgwc_s11_handle_release_access_bearers_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE, cause_value);
return;
}
@ -1235,8 +1255,9 @@ void sgwc_s11_handle_create_indirect_data_forwarding_tunnel_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE,
cause_value);
return;
@ -1253,8 +1274,9 @@ void sgwc_s11_handle_create_indirect_data_forwarding_tunnel_request(
for (i = 0; req->bearer_contexts[i].presence; i++) {
if (req->bearer_contexts[i].eps_bearer_id.presence == 0) {
ogs_error("No EBI");
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE,
OGS_GTP2_CAUSE_MANDATORY_IE_MISSING);
return;
@ -1276,8 +1298,9 @@ void sgwc_s11_handle_create_indirect_data_forwarding_tunnel_request(
rv = ogs_gtp2_f_teid_to_ip(req_teid, &tunnel->remote_ip);
if (rv != OGS_OK) {
ogs_gtp_send_error_message(s11_xact,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE,
OGS_GTP2_CAUSE_MANDATORY_IE_MISSING);
return;
@ -1311,8 +1334,9 @@ void sgwc_s11_handle_create_indirect_data_forwarding_tunnel_request(
rv = ogs_gtp2_f_teid_to_ip(req_teid, &tunnel->remote_ip);
if (rv != OGS_OK) {
ogs_gtp_send_error_message(s11_xact,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE,
OGS_GTP2_CAUSE_MANDATORY_IE_MISSING);
return;
@ -1366,8 +1390,9 @@ void sgwc_s11_handle_delete_indirect_data_forwarding_tunnel_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE,
cause_value);
return;
@ -1441,8 +1466,9 @@ void sgwc_s11_handle_bearer_resource_command(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value);
return;
}
@ -1462,8 +1488,9 @@ void sgwc_s11_handle_bearer_resource_command(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value);
return;
}
@ -1483,6 +1510,7 @@ void sgwc_s11_handle_bearer_resource_command(
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
message->h.type = OGS_GTP2_BEARER_RESOURCE_COMMAND_TYPE;
message->h.teid_presence = OGS_GTP2_TEID_PRESENCE;
message->h.teid = sess->pgw_s5c_teid;
pkbuf = ogs_gtp2_build_msg(message);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024444 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -122,8 +122,9 @@ void sgwc_s5c_handle_create_session_response(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
@ -160,8 +161,9 @@ void sgwc_s5c_handle_create_session_response(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
@ -185,8 +187,10 @@ void sgwc_s5c_handle_create_session_response(
bearer_cause = cause->value;
if (bearer_cause != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("GTP Bearer Cause [VALUE:%d]", bearer_cause);
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE :
OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, bearer_cause);
return;
}
@ -199,8 +203,9 @@ void sgwc_s5c_handle_create_session_response(
session_cause !=
OGS_GTP2_CAUSE_NEW_PDN_TYPE_DUE_TO_SINGLE_ADDRESS_BEARER_ONLY) {
ogs_error("GTP Cause [VALUE:%d]", session_cause);
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, session_cause);
return;
}
@ -233,8 +238,10 @@ void sgwc_s5c_handle_create_session_response(
bearer = sgwc_bearer_find_by_sess_ebi(sess,
rsp->bearer_contexts_created[i].eps_bearer_id.u8);
if (!bearer) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE :
OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_MANDATORY_IE_MISSING);
return;
@ -253,8 +260,10 @@ void sgwc_s5c_handle_create_session_response(
rv = ogs_gtp2_f_teid_to_ip(pgw_s5u_teid, &ul_tunnel->remote_ip);
if (rv != OGS_OK) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE :
OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_MANDATORY_IE_MISSING);
return;
@ -354,13 +363,15 @@ void sgwc_s5c_handle_modify_bearer_response(
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
if (modify_action == OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST)
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
else
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -376,13 +387,15 @@ void sgwc_s5c_handle_modify_bearer_response(
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
if (modify_action == OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST)
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
else
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -394,13 +407,15 @@ void sgwc_s5c_handle_modify_bearer_response(
if (session_cause != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_error("GTP Cause [VALUE:%d]", session_cause);
if (modify_action == OGS_GTP_MODIFY_IN_PATH_SWITCH_REQUEST)
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, session_cause);
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, session_cause);
else
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, session_cause);
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, session_cause);
return;
}
@ -420,6 +435,7 @@ void sgwc_s5c_handle_modify_bearer_response(
sgwc_gtp_send_create_session_response(sess, s11_xact));
} else {
message->h.type = OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE;
message->h.teid_presence = OGS_GTP2_TEID_PRESENCE;
message->h.teid = sgwc_ue->mme_s11_teid;
pkbuf = ogs_gtp2_build_msg(message);
@ -493,8 +509,9 @@ void sgwc_s5c_handle_delete_session_response(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
@ -573,7 +590,9 @@ void sgwc_s5c_handle_create_bearer_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
ogs_gtp2_send_error_message(s5c_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -601,7 +620,9 @@ void sgwc_s5c_handle_create_bearer_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
ogs_gtp2_send_error_message(s5c_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -631,7 +652,9 @@ void sgwc_s5c_handle_create_bearer_request(
rv = ogs_gtp2_f_teid_to_ip(pgw_s5u_teid, &ul_tunnel->remote_ip);
if (rv != OGS_OK) {
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
ogs_gtp2_send_error_message(s5c_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE,
OGS_GTP2_CAUSE_MANDATORY_IE_MISSING);
return;
@ -709,7 +732,9 @@ void sgwc_s5c_handle_update_bearer_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
ogs_gtp2_send_error_message(s5c_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_UPDATE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -729,6 +754,7 @@ void sgwc_s5c_handle_update_bearer_request(
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
message->h.type = OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE;
message->h.teid_presence = OGS_GTP2_TEID_PRESENCE;
message->h.teid = sgwc_ue->mme_s11_teid;
pkbuf = ogs_gtp2_build_msg(message);
@ -850,7 +876,9 @@ void sgwc_s5c_handle_delete_bearer_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s5c_xact, sess ? sess->pgw_s5c_teid : 0,
ogs_gtp2_send_error_message(s5c_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -870,6 +898,7 @@ void sgwc_s5c_handle_delete_bearer_request(
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
message->h.type = OGS_GTP2_DELETE_BEARER_REQUEST_TYPE;
message->h.teid_presence = OGS_GTP2_TEID_PRESENCE;
message->h.teid = sgwc_ue->mme_s11_teid;
pkbuf = ogs_gtp2_build_msg(message);
@ -970,6 +999,8 @@ void sgwc_s5c_handle_bearer_resource_failure_indication(
cause_value = OGS_GTP2_CAUSE_MANDATORY_IE_MISSING;
}
ogs_gtp_send_error_message(s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -245,8 +245,9 @@ void sgwc_sxa_handle_session_establishment_response(
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
if (sess) sgwc_ue = sess->sgwc_ue;
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
@ -269,10 +270,11 @@ void sgwc_sxa_handle_session_establishment_response(
if (dl_tunnel->local_addr == NULL && dl_tunnel->local_addr6 == NULL) {
ogs_error("No UP F-TEID");
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_GRE_KEY_NOT_FOUND);
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_GRE_KEY_NOT_FOUND);
return;
}
@ -347,6 +349,7 @@ void sgwc_sxa_handle_session_establishment_response(
memset(&send_message, 0, sizeof(ogs_gtp2_message_t));
send_message.h.type = OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE;
send_message.h.teid_presence = OGS_GTP2_TEID_PRESENCE;
send_message.h.teid = sess->pgw_s5c_teid;
/* Send Control Plane(DL) : SGW-S5C */
@ -396,6 +399,7 @@ void sgwc_sxa_handle_session_establishment_response(
/* Create Session Request */
recv_message->h.type = OGS_GTP2_CREATE_SESSION_REQUEST_TYPE;
recv_message->h.teid_presence = OGS_GTP2_TEID_PRESENCE;
recv_message->h.teid = sess->pgw_s5c_teid;
/* Send Control Plane(DL) : SGW-S5C */
@ -581,9 +585,10 @@ void sgwc_sxa_handle_session_modification_response(
s5c_xact = pfcp_xact->assoc_xact;
if (s5c_xact) {
ogs_gtp_send_error_message(
s5c_xact, sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE, cause_value);
ogs_gtp2_send_error_message(s5c_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE, cause_value);
}
sgwc_bearer_remove(bearer);
@ -591,8 +596,9 @@ void sgwc_sxa_handle_session_modification_response(
s5c_xact = pfcp_xact->assoc_xact;
ogs_assert(s5c_xact);
ogs_gtp_send_error_message(
s5c_xact, sess ? sess->pgw_s5c_teid : 0,
ogs_gtp2_send_error_message(s5c_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->pgw_s5c_teid : 0,
OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE, cause_value);
@ -601,16 +607,20 @@ void sgwc_sxa_handle_session_modification_response(
s11_xact = pfcp_xact->assoc_xact;
ogs_assert(s11_xact);
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE :
OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, cause_value);
} else if (flags & OGS_PFCP_MODIFY_DL_ONLY) {
s11_xact = pfcp_xact->assoc_xact;
ogs_assert(s11_xact);
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE :
OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
} else {
ogs_fatal("Invalid modify_flags[0x%llx]", (long long)flags);
@ -620,9 +630,10 @@ void sgwc_sxa_handle_session_modification_response(
s11_xact = pfcp_xact->assoc_xact;
ogs_assert(s11_xact);
ogs_gtp_send_error_message(
s11_xact, sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE, cause_value);
ogs_gtp2_send_error_message(s11_xact,
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sgwc_ue ? sgwc_ue->mme_s11_teid : 0,
OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE, cause_value);
}
ogs_pfcp_xact_commit(pfcp_xact);
@ -694,6 +705,7 @@ void sgwc_sxa_handle_session_modification_response(
send_message.h.type =
OGS_GTP2_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE;
send_message.h.teid_presence = OGS_GTP2_TEID_PRESENCE;
send_message.h.teid = sgwc_ue->mme_s11_teid;
pkbuf = ogs_gtp2_build_msg(&send_message);
@ -720,6 +732,7 @@ void sgwc_sxa_handle_session_modification_response(
if (s5c_xact) {
ogs_assert(recv_message);
recv_message->h.type = OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE;
recv_message->h.teid_presence = OGS_GTP2_TEID_PRESENCE;
recv_message->h.teid = sess->pgw_s5c_teid;
pkbuf = ogs_gtp2_build_msg(recv_message);
@ -769,6 +782,7 @@ void sgwc_sxa_handle_session_modification_response(
gtp_req->bearer_contexts.s1_u_enodeb_f_teid.len = len;
recv_message->h.type = OGS_GTP2_CREATE_BEARER_REQUEST_TYPE;
recv_message->h.teid_presence = OGS_GTP2_TEID_PRESENCE;
recv_message->h.teid = sgwc_ue->mme_s11_teid;
pkbuf = ogs_gtp2_build_msg(recv_message);
@ -836,6 +850,7 @@ void sgwc_sxa_handle_session_modification_response(
gtp_rsp->bearer_contexts.s5_s8_u_pgw_f_teid.len = len;
recv_message->h.type = OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE;
recv_message->h.teid_presence = OGS_GTP2_TEID_PRESENCE;
recv_message->h.teid = sess->pgw_s5c_teid;
pkbuf = ogs_gtp2_build_msg(recv_message);
@ -962,6 +977,7 @@ void sgwc_sxa_handle_session_modification_response(
send_message.h.type =
OGS_GTP2_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE;
send_message.h.teid_presence = OGS_GTP2_TEID_PRESENCE;
send_message.h.teid = sgwc_ue->mme_s11_teid;
pkbuf = ogs_gtp2_build_msg(&send_message);
@ -1046,6 +1062,7 @@ void sgwc_sxa_handle_session_modification_response(
}
recv_message->h.type = OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE;
recv_message->h.teid_presence = OGS_GTP2_TEID_PRESENCE;
recv_message->h.teid = sgwc_ue->mme_s11_teid;
pkbuf = ogs_gtp2_build_msg(recv_message);
@ -1083,6 +1100,7 @@ void sgwc_sxa_handle_session_modification_response(
if (indication && indication->handover_indication) {
recv_message->h.type = OGS_GTP2_MODIFY_BEARER_REQUEST_TYPE;
recv_message->h.teid_presence = OGS_GTP2_TEID_PRESENCE;
recv_message->h.teid = sess->pgw_s5c_teid;
pkbuf = ogs_gtp2_build_msg(recv_message);
@ -1168,6 +1186,7 @@ void sgwc_sxa_handle_session_modification_response(
}
send_message.h.type = OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE;
send_message.h.teid_presence = OGS_GTP2_TEID_PRESENCE;
send_message.h.teid = sgwc_ue->mme_s11_teid;
pkbuf = ogs_gtp2_build_msg(&send_message);
@ -1233,6 +1252,7 @@ void sgwc_sxa_handle_session_modification_response(
send_message.h.type =
OGS_GTP2_RELEASE_ACCESS_BEARERS_RESPONSE_TYPE;
send_message.h.teid_presence = OGS_GTP2_TEID_PRESENCE;
send_message.h.teid = sgwc_ue->mme_s11_teid;
pkbuf = ogs_gtp2_build_msg(&send_message);
@ -1264,6 +1284,7 @@ void sgwc_sxa_handle_session_deletion_response(
{
int rv;
uint8_t cause_value = 0;
int teid_presence = OGS_GTP2_TEID_NO_PRESENCE;
uint32_t teid = 0;
sgwc_ue_t *sgwc_ue = NULL;
@ -1315,6 +1336,8 @@ void sgwc_sxa_handle_session_deletion_response(
* 2. SMF sends Delete Session Response to SGW/MME.
*/
if (sess) sgwc_ue = sess->sgwc_ue;
teid_presence =
sgwc_ue ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE;
teid = sgwc_ue ? sgwc_ue->mme_s11_teid : 0;
break;
case OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE:
@ -1331,6 +1354,8 @@ void sgwc_sxa_handle_session_deletion_response(
* - Bearer Resource Command
* - Delete Bearer Request/Response with DEDICATED BEARER.
*/
teid_presence =
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE;
teid = sess ? sess->pgw_s5c_teid : 0;
break;
default:
@ -1340,8 +1365,8 @@ void sgwc_sxa_handle_session_deletion_response(
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
if (gtp_xact) {
ogs_gtp_send_error_message(
gtp_xact, teid, gtp_message->h.type, cause_value);
ogs_gtp2_send_error_message(gtp_xact,
teid_presence, teid, gtp_message->h.type, cause_value);
}
return;
}
@ -1358,6 +1383,7 @@ void sgwc_sxa_handle_session_deletion_response(
* If gtp_message->h.type == OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE
* Then gtp_xact is S5C-XACT
*/
gtp_message->h.teid_presence = OGS_GTP2_TEID_PRESENCE;
gtp_message->h.teid = teid;
pkbuf = ogs_gtp2_build_msg(gtp_message);
@ -1419,7 +1445,8 @@ void sgwc_sxa_handle_session_report_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_pfcp_send_error_message(pfcp_xact, 0,
ogs_pfcp_send_error_message(pfcp_xact,
OGS_PFCP_SEID_NO_PRESENCE, 0,
OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE,
cause_value, 0);
return;
@ -1431,7 +1458,9 @@ void sgwc_sxa_handle_session_report_request(
if (!sgwc_ue->gnode) {
ogs_error("No SGWC-UE GTP Node");
ogs_pfcp_send_error_message(pfcp_xact, sess ? sess->sgwu_sxa_seid : 0,
ogs_pfcp_send_error_message(pfcp_xact,
sess ? OGS_PFCP_SEID_PRESENCE : OGS_PFCP_SEID_NO_PRESENCE,
sess ? sess->sgwu_sxa_seid : 0,
OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE,
OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND, 0);
return;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -180,6 +180,7 @@ int sgwu_pfcp_send_session_establishment_response(
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->sgwc_sxa_f_seid.seid;
sxabuf = sgwu_sxa_build_session_establishment_response(
@ -213,6 +214,7 @@ int sgwu_pfcp_send_session_modification_response(
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->sgwc_sxa_f_seid.seid;
sxabuf = sgwu_sxa_build_session_modification_response(
@ -245,6 +247,7 @@ int sgwu_pfcp_send_session_deletion_response(ogs_pfcp_xact_t *xact,
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->sgwc_sxa_f_seid.seid;
sxabuf = sgwu_sxa_build_session_deletion_response(h.type, sess);
@ -295,6 +298,7 @@ int sgwu_pfcp_send_session_report_request(
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_REPORT_REQUEST_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->sgwc_sxa_f_seid.seid;
xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess);

View File

@ -318,10 +318,6 @@ void sgwu_pfcp_state_associated(ogs_fsm_t *s, sgwu_event_t *e)
}
break;
case SGWU_EVT_SXA_NO_HEARTBEAT:
/* 'node' context was removed in ogs_pfcp_xact_delete(xact)
* So, we should not use PFCP node here */
ogs_warn("No Heartbeat from SGW-C [%s]:%d",
OGS_ADDR(addr, buf), OGS_PORT(addr));
OGS_FSM_TRAN(s, sgwu_pfcp_state_will_associate);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -45,7 +45,8 @@ void sgwu_sxa_handle_session_establishment_request(
if (!sess) {
ogs_error("No Context");
ogs_pfcp_send_error_message(xact, 0,
ogs_pfcp_send_error_message(xact,
OGS_PFCP_SEID_NO_PRESENCE, 0,
OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE,
OGS_PFCP_CAUSE_MANDATORY_IE_MISSING, 0);
return;
@ -142,7 +143,9 @@ void sgwu_sxa_handle_session_establishment_request(
cleanup:
ogs_pfcp_sess_clear(&sess->pfcp);
ogs_pfcp_send_error_message(xact, sess ? sess->sgwu_sxa_seid : 0,
ogs_pfcp_send_error_message(xact,
sess ? OGS_PFCP_SEID_PRESENCE : OGS_PFCP_SEID_NO_PRESENCE,
sess ? sess->sgwu_sxa_seid : 0,
OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE,
cause_value, offending_ie_value);
}
@ -168,7 +171,8 @@ void sgwu_sxa_handle_session_modification_request(
if (!sess) {
ogs_error("No Context");
ogs_pfcp_send_error_message(xact, 0,
ogs_pfcp_send_error_message(xact,
OGS_PFCP_SEID_NO_PRESENCE, 0,
OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE,
OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND, 0);
return;
@ -309,7 +313,9 @@ void sgwu_sxa_handle_session_modification_request(
cleanup:
ogs_pfcp_sess_clear(&sess->pfcp);
ogs_pfcp_send_error_message(xact, sess ? sess->sgwu_sxa_seid : 0,
ogs_pfcp_send_error_message(xact,
sess ? OGS_PFCP_SEID_PRESENCE : OGS_PFCP_SEID_NO_PRESENCE,
sess ? sess->sgwu_sxa_seid : 0,
OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE,
cause_value, offending_ie_value);
}
@ -325,7 +331,8 @@ void sgwu_sxa_handle_session_deletion_request(
if (!sess) {
ogs_error("No Context");
ogs_pfcp_send_error_message(xact, 0,
ogs_pfcp_send_error_message(xact,
OGS_PFCP_SEID_NO_PRESENCE, 0,
OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE,
OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND, 0);
return;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -363,6 +363,7 @@ void smf_bearer_binding(smf_sess_t *sess)
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sess->sgw_s5c_teid;
pkbuf = smf_s5c_build_update_bearer_request(
@ -439,6 +440,7 @@ int smf_gtp2_send_create_bearer_request(smf_bearer_t *bearer)
ogs_assert(sess);
h.type = OGS_GTP2_CREATE_BEARER_REQUEST_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sess->sgw_s5c_teid;
memset(&tft, 0, sizeof tft);

View File

@ -1,6 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -74,7 +73,9 @@ static void send_gtp_create_err_msg(const smf_sess_t *sess,
ogs_gtp1_send_error_message(gtp_xact, sess->sgw_s5c_teid,
OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE, gtp_cause);
else
ogs_gtp2_send_error_message(gtp_xact, sess->sgw_s5c_teid,
ogs_gtp2_send_error_message(gtp_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess->sgw_s5c_teid,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE, gtp_cause);
}
@ -85,7 +86,9 @@ static void send_gtp_delete_err_msg(const smf_sess_t *sess,
ogs_gtp1_send_error_message(gtp_xact, sess->sgw_s5c_teid,
OGS_GTP1_DELETE_PDP_CONTEXT_RESPONSE_TYPE, gtp_cause);
else
ogs_gtp2_send_error_message(gtp_xact, sess->sgw_s5c_teid,
ogs_gtp2_send_error_message(gtp_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess->sgw_s5c_teid,
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, gtp_cause);
}
@ -716,6 +719,9 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
ogs_pfcp_xact_t *pfcp_xact = NULL;
ogs_pfcp_message_t *pfcp_message = NULL;
ogs_diam_gy_message_t *gy_message = NULL;
uint32_t diam_err;
ogs_nas_5gs_message_t *nas_message = NULL;
ogs_sbi_stream_t *stream = NULL;
@ -772,8 +778,10 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
sess, e->gtp_xact,
&gtp2_message->delete_session_request);
if (gtp2_cause != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp2_send_error_message(e->gtp_xact, sess->sgw_s5c_teid,
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, gtp2_cause);
ogs_gtp2_send_error_message(e->gtp_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess->sgw_s5c_teid,
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE, gtp2_cause);
return;
}
OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion);
@ -829,6 +837,24 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e)
}
break;
case SMF_EVT_GY_MESSAGE:
gy_message = e->gy_message;
ogs_assert(gy_message);
switch(gy_message->cmd_code) {
case OGS_DIAM_GY_CMD_CODE_CREDIT_CONTROL:
switch (gy_message->cc_request_type) {
case OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST:
ogs_assert(e->pfcp_xact);
diam_err = smf_gy_handle_cca_update_request(sess, gy_message, e->pfcp_xact);
if (diam_err != ER_DIAMETER_SUCCESS)
OGS_FSM_TRAN(s, smf_gsm_state_wait_pfcp_deletion);
break;
}
break;
}
break;
case OGS_EVENT_SBI_SERVER:
sbi_message = e->h.sbi.message;
ogs_assert(sbi_message);
@ -1465,7 +1491,6 @@ void smf_gsm_state_wait_epc_auth_release(ogs_fsm_t *s, smf_event_t *e)
case OGS_DIAM_GY_CMD_CODE_CREDIT_CONTROL:
switch(gy_message->cc_request_type) {
case OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST:
ogs_assert(e->gtp_xact);
diam_err = smf_gy_handle_cca_termination_request(sess,
gy_message, e->gtp_xact);
sess->sm_data.gy_ccr_term_in_flight = false;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -444,6 +444,7 @@ int smf_gtp2_send_create_session_response(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sess->sgw_s5c_teid;
pkbuf = smf_s5c_build_create_session_response(h.type, sess);
@ -478,6 +479,7 @@ int smf_gtp2_send_modify_bearer_response(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sess->sgw_s5c_teid;
pkbuf = smf_s5c_build_modify_bearer_response(
@ -511,6 +513,7 @@ int smf_gtp2_send_delete_session_response(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sess->sgw_s5c_teid;
pkbuf = smf_s5c_build_delete_session_response(h.type, sess);
@ -548,6 +551,7 @@ int smf_gtp2_send_delete_bearer_request(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_DELETE_BEARER_REQUEST_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sess->sgw_s5c_teid;
pkbuf = smf_s5c_build_delete_bearer_request(

View File

@ -149,7 +149,7 @@ uint32_t smf_gy_handle_cca_initial_request(
return ER_DIAMETER_SUCCESS;
}
void smf_gy_handle_cca_update_request(
uint32_t smf_gy_handle_cca_update_request(
smf_sess_t *sess, ogs_diam_gy_message_t *gy_message,
ogs_pfcp_xact_t *pfcp_xact)
{
@ -175,10 +175,14 @@ void smf_gy_handle_cca_update_request(
if (gy_message->result_code != ER_DIAMETER_SUCCESS) {
ogs_warn("Gy CCA Update Diameter failure: res=%u err=%u",
gy_message->result_code, *gy_message->err);
// TODO: generate new gtp_xact from sess here? */
//ogs_assert(OGS_OK ==
// smf_epc_pfcp_send_session_deletion_request(sess, gtp_xact));
return;
return gy_message->err ? *gy_message->err :
ER_DIAMETER_AUTHENTICATION_REJECTED;
}
if (gy_message->cca.result_code != ER_DIAMETER_SUCCESS) {
ogs_warn("Gy CCA Update Diameter Multiple-Services-Credit-Control Result-Code=%u",
gy_message->cca.result_code);
return gy_message->cca.err ? *gy_message->cca.err :
ER_DIAMETER_AUTHENTICATION_REJECTED;
}
bearer = smf_default_bearer_in_sess(sess);
@ -234,6 +238,7 @@ void smf_gy_handle_cca_update_request(
OGS_GTP1_CAUSE_REACTIACTION_REQUESTED);
ogs_assert(rv == OGS_OK);
}
return ER_DIAMETER_SUCCESS;
}
uint32_t smf_gy_handle_cca_termination_request(
@ -242,7 +247,6 @@ uint32_t smf_gy_handle_cca_termination_request(
{
ogs_assert(sess);
ogs_assert(gy_message);
ogs_assert(gtp_xact);
ogs_debug("[SMF] Delete Session Response");
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",

View File

@ -30,7 +30,7 @@ extern "C" {
uint32_t smf_gy_handle_cca_initial_request(
smf_sess_t *sess, ogs_diam_gy_message_t *gy_message,
ogs_gtp_xact_t *gtp_xact);
void smf_gy_handle_cca_update_request(
uint32_t smf_gy_handle_cca_update_request(
smf_sess_t *sess, ogs_diam_gy_message_t *gy_message,
ogs_pfcp_xact_t *pfcp_xact);
uint32_t smf_gy_handle_cca_termination_request(

View File

@ -198,7 +198,7 @@ static void fill_qos_information(smf_sess_t *sess, struct avp *parent_avp)
union avp_value val;
struct avp *avpch1, *avpch2, *avpch3;
ret = fd_msg_avp_new(ogs_diam_gx_qos_information, 0, &avpch1);
ret = fd_msg_avp_new(ogs_diam_gy_qos_information, 0, &avpch1);
ogs_assert(ret == 0);
/* QoS-Class-Identifier */
@ -325,41 +325,27 @@ static void fill_multiple_services_credit_control_ccr(smf_sess_t *sess,
/* QoS-Information */
fill_qos_information(sess, avp);
/* 3GPP-RAT-Type, TS 29.061 16.4.7.2 21 */
/* GGSN: TS 29.060 7.7.50, PGW: TS 29.274 8.17 */
ret = fd_msg_avp_new(ogs_diam_gy_3gpp_rat_type, 0, &avpch1);
ogs_assert(ret == 0);
val.os.data = (uint8_t*)&sess->gtp_rat_type;
val.os.len = 1;
ret = fd_msg_avp_setvalue (avpch1, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
ogs_assert(ret == 0);
/* Multiple Services AVP add to req: */
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
ogs_assert(ret == 0);
}
/* TS 32.299 7.2.192 Service-Information AVP for CCR */
static void fill_service_information_ccr(smf_sess_t *sess,
uint32_t cc_request_type, struct msg *req)
/* TS 32.299 7.2.158 PS-Information AVP for CCR */
static void fill_ps_information(smf_sess_t *sess, uint32_t cc_request_type,
struct avp *avp)
{
int ret;
union avp_value val;
struct avp *avp;
struct avp *avpch1, *avpch2, *avpch3;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
char buf[OGS_PLMNIDSTRLEN];
char digit;
/* Service-Information, TS 32.299 sec 7.2.192 */
ret = fd_msg_avp_new(ogs_diam_gy_service_information, 0, &avp);
/* PS-Information, TS 32.299 sec 7.2.158 */
ret = fd_msg_avp_new(ogs_diam_gy_ps_information, 0, &avpch1);
ogs_assert(ret == 0);
/* 3GPP-Charging-Id, 3GPP TS 29.061 16.4.7.2 2 */
ret = fd_msg_avp_new(ogs_diam_gy_3gpp_charging_id, 0, &avpch2);
@ -556,6 +542,17 @@ static void fill_service_information_ccr(smf_sess_t *sess,
/* 3GPP-User-Location-Info, 3GPP TS 29.061 16.4.7.2 22 */
smf_fd_msg_avp_add_3gpp_uli(sess, (struct msg *)avpch1);
/* 3GPP-RAT-Type, TS 29.061 16.4.7.2 21 */
/* GGSN: TS 29.060 7.7.50, PGW: TS 29.274 8.17 */
ret = fd_msg_avp_new(ogs_diam_gy_3gpp_rat_type, 0, &avpch2);
ogs_assert(ret == 0);
val.os.data = (uint8_t*)&sess->gtp_rat_type;
val.os.len = 1;
ret = fd_msg_avp_setvalue(avpch2, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2);
ogs_assert(ret == 0);
if (sess->smf_ue->imeisv_len > 0) {
/* User-Equipment-Info, 3GPP TS 32.299 7.1.17 */
ret = fd_msg_avp_new(ogs_diam_gy_user_equipment_info, 0, &avpch2);
@ -585,9 +582,25 @@ static void fill_service_information_ccr(smf_sess_t *sess,
ogs_assert(ret == 0);
}
/* PS-Information AVP add to req: */
/* PS-Information AVP add to parent AVP (Service-Information): */
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
ogs_assert(ret == 0);
}
/* TS 32.299 7.2.192 Service-Information AVP for CCR */
static void fill_service_information_ccr(smf_sess_t *sess,
uint32_t cc_request_type, struct msg *req)
{
int ret;
struct avp *avp;
/* Service-Information, TS 32.299 sec 7.2.192 */
ret = fd_msg_avp_new(ogs_diam_gy_service_information, 0, &avp);
ogs_assert(ret == 0);
/* PS-Information, TS 32.299 sec 7.2.158 */
fill_ps_information(sess, cc_request_type, avp);
/* Service-Information AVP add to req: */
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
@ -612,7 +625,6 @@ void smf_gy_send_ccr(smf_sess_t *sess, void *xact,
const char *service_context_id = "32251@3gpp.org";
uint32_t timestamp, req_slot;
ogs_assert(xact);
ogs_assert(sess);
ogs_assert(sess->ipv4 || sess->ipv6);
@ -1004,6 +1016,9 @@ static void smf_gy_cca_cb(void *data, struct msg **msg)
/* Set Credit Control Command */
gy_message->cmd_code = OGS_DIAM_GY_CMD_CODE_CREDIT_CONTROL;
/* Initialize some values: */
gy_message->cca.result_code = ER_DIAMETER_SUCCESS;
/* Value of Result Code */
ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp);
ogs_assert(ret == 0);
@ -1115,6 +1130,10 @@ static void smf_gy_cca_cb(void *data, struct msg **msg)
ret = fd_msg_avp_hdr(avpch1, &hdr);
ogs_assert(ret == 0);
switch (hdr->avp_code) {
case AC_RESULT_CODE:
gy_message->cca.result_code = hdr->avp_value->u32;
gy_message->cca.err = &gy_message->cca.result_code;
break;
case OGS_DIAM_GY_AVP_CODE_GRANTED_SERVICE_UNIT:
rv = decode_granted_service_unit(
&gy_message->cca.granted, avpch1, &error);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -971,6 +971,7 @@ void smf_epc_n4_handle_session_modification_response(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.teid = sess->sgw_s5c_teid;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.type = OGS_GTP2_DELETE_BEARER_REQUEST_TYPE;
pkbuf = smf_s5c_build_delete_bearer_request(
@ -1182,7 +1183,8 @@ void smf_n4_handle_session_report_request(
}
if (cause_value != OGS_PFCP_CAUSE_REQUEST_ACCEPTED) {
ogs_pfcp_send_error_message(pfcp_xact, 0,
ogs_pfcp_send_error_message(pfcp_xact,
OGS_PFCP_SEID_NO_PRESENCE, 0,
OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE,
cause_value, 0);
return;
@ -1222,7 +1224,8 @@ void smf_n4_handle_session_report_request(
if (paging_policy_indication_value) {
ogs_warn("Not implement - "
"Paging Policy Indication Value");
ogs_pfcp_send_error_message(pfcp_xact, 0,
ogs_pfcp_send_error_message(pfcp_xact,
OGS_PFCP_SEID_NO_PRESENCE, 0,
OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE,
OGS_PFCP_CAUSE_SERVICE_NOT_SUPPORTED, 0);
return;
@ -1232,7 +1235,8 @@ void smf_n4_handle_session_report_request(
qos_flow = smf_qos_flow_find_by_qfi(sess, qfi);
if (!qos_flow) {
ogs_error("Cannot find the QoS Flow[%d]", qfi);
ogs_pfcp_send_error_message(pfcp_xact, 0,
ogs_pfcp_send_error_message(pfcp_xact,
OGS_PFCP_SEID_NO_PRESENCE, 0,
OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE,
OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND, 0);
return;
@ -1257,7 +1261,8 @@ void smf_n4_handle_session_report_request(
if (!pdr) {
ogs_error("No Context");
ogs_pfcp_send_error_message(pfcp_xact, 0,
ogs_pfcp_send_error_message(pfcp_xact,
OGS_PFCP_SEID_NO_PRESENCE, 0,
OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE,
OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND, 0);
return;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -222,8 +222,11 @@ static void sess_5gc_timeout(ogs_pfcp_xact_t *xact, void *data)
ogs_assert(xact);
ogs_assert(data);
sess = data;
ogs_assert(sess);
sess = smf_sess_cycle(data);
if (!sess) {
ogs_warn("Session has already been removed");
return;
}
smf_ue = sess->smf_ue;
ogs_assert(smf_ue);
@ -288,7 +291,21 @@ static void sess_5gc_timeout(ogs_pfcp_xact_t *xact, void *data)
ogs_free(strerror);
smf_sess_remove(sess);
/* We mustn't remove sess here. Removing a session may delete PFCP xact
timers and we must not delete any timers from within a timer
callback. Instead, we shall emit a new event to trigger session
removal from pfcp-sm state machine. */
e = smf_event_new(SMF_EVT_N4_TIMER);
ogs_assert(e);
e->sess = sess;
e->h.timer_id = SMF_TIMER_PFCP_NO_DELETION_RESPONSE;
e->pfcp_node = sess->pfcp_node;
rv = ogs_queue_push(ogs_app()->queue, e);
if (rv != OGS_OK) {
ogs_error("ogs_queue_push() failed:%d", (int)rv);
ogs_event_free(e);
}
break;
default:
ogs_error("Not implemented [type:%d]", type);
@ -353,6 +370,7 @@ int smf_pfcp_send_modify_list(
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_MODIFICATION_REQUEST_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->upf_n4_seid;
n4buf = (*modify_list)(h.type, sess, xact);
@ -430,6 +448,7 @@ int smf_5gc_pfcp_send_session_establishment_request(
* over N4 towards another SMF or another PFCP entity in the SMF
* as specified in clause 5.22.2 and clause 5.22.3.
*/
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->upf_n4_seid;
n4buf = smf_n4_build_session_establishment_request(h.type, sess, xact);
@ -532,6 +551,7 @@ int smf_5gc_pfcp_send_session_deletion_request(
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_DELETION_REQUEST_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->upf_n4_seid;
n4buf = smf_n4_build_session_deletion_request(h.type, sess);
@ -605,6 +625,7 @@ int smf_epc_pfcp_send_session_establishment_request(
* over N4 towards another SMF or another PFCP entity in the SMF
* as specified in clause 5.22.2 and clause 5.22.3.
*/
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->upf_n4_seid;
n4buf = smf_n4_build_session_establishment_request(h.type, sess, xact);
@ -748,6 +769,7 @@ int smf_epc_pfcp_send_session_deletion_request(
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_DELETION_REQUEST_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->upf_n4_seid;
n4buf = smf_n4_build_session_deletion_request(h.type, sess);
@ -846,6 +868,7 @@ int smf_pfcp_send_session_report_response(
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->upf_n4_seid;
sxabuf = ogs_pfcp_build_session_report_response(h.type, cause);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -117,14 +117,21 @@ void smf_pfcp_state_will_associate(ogs_fsm_t *s, smf_event_t *e)
ogs_pfcp_cp_send_association_setup_request(node, node_timeout);
break;
case SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE:
sess = e->sess;
sess = smf_sess_cycle(sess);
sess = smf_sess_cycle(e->sess);
if (!sess) {
ogs_warn("Session has already been removed");
break;
}
ogs_fsm_dispatch(&sess->sm, e);
break;
case SMF_TIMER_PFCP_NO_DELETION_RESPONSE:
sess = smf_sess_cycle(e->sess);
if (!sess) {
ogs_warn("Session has already been removed");
break;
}
SMF_SESS_CLEAR(sess);
break;
default:
ogs_error("Unknown timer[%s:%d]",
smf_timer_get_name(e->h.timer_id), e->h.timer_id);
@ -317,7 +324,8 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
OGS_GTP1_CREATE_PDP_CONTEXT_RESPONSE_TYPE,
OGS_GTP1_CAUSE_CONTEXT_NOT_FOUND);
else
ogs_gtp2_send_error_message(gtp_xact, 0,
ogs_gtp2_send_error_message(gtp_xact,
OGS_GTP2_TEID_NO_PRESENCE, 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND);
break;
@ -352,7 +360,8 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
OGS_GTP1_DELETE_PDP_CONTEXT_RESPONSE_TYPE,
OGS_GTP1_CAUSE_CONTEXT_NOT_FOUND);
else
ogs_gtp2_send_error_message(gtp_xact, 0,
ogs_gtp2_send_error_message(gtp_xact,
OGS_GTP2_TEID_NO_PRESENCE, 0,
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND);
break;
@ -384,14 +393,21 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
ogs_pfcp_send_heartbeat_request(node, node_timeout));
break;
case SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE:
sess = e->sess;
sess = smf_sess_cycle(sess);
sess = smf_sess_cycle(e->sess);
if (!sess) {
ogs_warn("Session has already been removed");
break;
}
ogs_fsm_dispatch(&sess->sm, e);
break;
case SMF_TIMER_PFCP_NO_DELETION_RESPONSE:
sess = smf_sess_cycle(e->sess);
if (!sess) {
ogs_warn("Session has already been removed");
break;
}
SMF_SESS_CLEAR(sess);
break;
default:
ogs_error("Unknown timer[%s:%d]",
smf_timer_get_name(e->h.timer_id), e->h.timer_id);
@ -399,12 +415,19 @@ void smf_pfcp_state_associated(ogs_fsm_t *s, smf_event_t *e)
}
break;
case SMF_EVT_N4_NO_HEARTBEAT:
/* 'node' context was removed in ogs_pfcp_xact_delete(xact)
* So, we should not use PFCP node here */
ogs_warn("No Heartbeat from UPF [%s]:%d",
OGS_ADDR(addr, buf), OGS_PORT(addr));
/*
* reselect_upf() should not be executed on node_timeout
* because the timer cannot be deleted in the timer expiration function.
*
* Note that reselct_upf contains SMF_SESS_CLEAR.
*/
node = e->pfcp_node;
ogs_assert(node);
reselect_upf(node);
OGS_FSM_TRAN(s, smf_pfcp_state_will_associate);
break;
default:
@ -548,7 +571,6 @@ static void node_timeout(ogs_pfcp_xact_t *xact, void *data)
switch (type) {
case OGS_PFCP_HEARTBEAT_REQUEST_TYPE:
ogs_assert(data);
reselect_upf(data);
e = smf_event_new(SMF_EVT_N4_NO_HEARTBEAT);
e->pfcp_node = data;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -504,7 +504,9 @@ void smf_s5c_handle_modify_bearer_request(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp2_send_error_message(gtp_xact, sess ? sess->sgw_s5c_teid : 0,
ogs_gtp2_send_error_message(gtp_xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->sgw_s5c_teid : 0,
OGS_GTP2_MODIFY_BEARER_RESPONSE_TYPE, cause_value);
return;
}
@ -1186,7 +1188,9 @@ void smf_s5c_handle_bearer_resource_command(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp2_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0,
ogs_gtp2_send_error_message(xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->sgw_s5c_teid : 0,
OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value);
return;
}
@ -1211,7 +1215,9 @@ void smf_s5c_handle_bearer_resource_command(
}
if (cause_value != OGS_GTP2_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp2_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0,
ogs_gtp2_send_error_message(xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->sgw_s5c_teid : 0,
OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value);
return;
}
@ -1240,8 +1246,10 @@ void smf_s5c_handle_bearer_resource_command(
pf = smf_pf_find_by_id(bearer, tft.pf[i].identifier+1);
if (pf) {
if (reconfigure_packet_filter(pf, &tft, i) < 0) {
ogs_gtp2_send_error_message(
xact, sess ? sess->sgw_s5c_teid : 0,
ogs_gtp2_send_error_message(xact,
sess ? OGS_GTP2_TEID_PRESENCE :
OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->sgw_s5c_teid : 0,
OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE,
OGS_GTP2_CAUSE_SEMANTIC_ERRORS_IN_PACKET_FILTER);
return;
@ -1309,8 +1317,9 @@ void smf_s5c_handle_bearer_resource_command(
ogs_assert(pf);
if (reconfigure_packet_filter(pf, &tft, i) < 0) {
ogs_gtp2_send_error_message(
xact, sess ? sess->sgw_s5c_teid : 0,
ogs_gtp2_send_error_message(xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->sgw_s5c_teid : 0,
OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE,
OGS_GTP2_CAUSE_SEMANTIC_ERRORS_IN_PACKET_FILTER);
return;
@ -1396,7 +1405,9 @@ void smf_s5c_handle_bearer_resource_command(
if (tft_update == 0 && tft_delete == 0 && qos_update == 0) {
/* No modification */
ogs_gtp2_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0,
ogs_gtp2_send_error_message(xact,
sess ? OGS_GTP2_TEID_PRESENCE : OGS_GTP2_TEID_NO_PRESENCE,
sess ? sess->sgw_s5c_teid : 0,
OGS_GTP2_BEARER_RESOURCE_FAILURE_INDICATION_TYPE,
OGS_GTP2_CAUSE_SERVICE_NOT_SUPPORTED);
return;
@ -1422,6 +1433,7 @@ void smf_s5c_handle_bearer_resource_command(
} else {
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.teid = sess->sgw_s5c_teid;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.type = OGS_GTP2_UPDATE_BEARER_REQUEST_TYPE;
pkbuf = smf_s5c_build_update_bearer_request(

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -144,7 +144,8 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
}
if (!sess) {
ogs_error("No Session");
ogs_gtp2_send_error_message(gtp_xact, 0,
ogs_gtp2_send_error_message(gtp_xact,
OGS_GTP2_TEID_NO_PRESENCE, 0,
OGS_GTP2_CREATE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND);
break;
@ -158,7 +159,8 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
smf_metrics_inst_gtp_node_inc(smf_gnode->metrics, SMF_METR_GTP_NODE_CTR_S5C_RX_DELETESESSIONREQ);
if (!sess) {
ogs_error("No Session");
ogs_gtp2_send_error_message(gtp_xact, 0,
ogs_gtp2_send_error_message(gtp_xact,
OGS_GTP2_TEID_NO_PRESENCE, 0,
OGS_GTP2_DELETE_SESSION_RESPONSE_TYPE,
OGS_GTP2_CAUSE_CONTEXT_NOT_FOUND);
break;
@ -328,23 +330,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
switch(gy_message->cmd_code) {
case OGS_DIAM_GY_CMD_CODE_CREDIT_CONTROL:
switch(gy_message->cc_request_type) {
case OGS_DIAM_GY_CC_REQUEST_TYPE_INITIAL_REQUEST:
ogs_fsm_dispatch(&sess->sm, e);
break;
case OGS_DIAM_GY_CC_REQUEST_TYPE_UPDATE_REQUEST:
ogs_assert(e->pfcp_xact);
smf_gy_handle_cca_update_request(
sess, gy_message, e->pfcp_xact);
break;
case OGS_DIAM_GY_CC_REQUEST_TYPE_TERMINATION_REQUEST:
ogs_fsm_dispatch(&sess->sm, e);
break;
default:
ogs_error("Not implemented(%d)", gy_message->cc_request_type);
break;
}
ogs_fsm_dispatch(&sess->sm, e);
break;
case OGS_DIAM_GY_CMD_RE_AUTH:
smf_gy_handle_re_auth_request(sess, gy_message);

View File

@ -42,6 +42,8 @@ const char *smf_timer_get_name(int timer_id)
return "SMF_TIMER_PFCP_NO_HEARTBEAT";
case SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE:
return "SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE";
case SMF_TIMER_PFCP_NO_DELETION_RESPONSE:
return "SMF_TIMER_PFCP_NO_DELETION_RESPONSE";
default:
break;
}

View File

@ -33,6 +33,7 @@ typedef enum {
SMF_TIMER_PFCP_ASSOCIATION,
SMF_TIMER_PFCP_NO_HEARTBEAT,
SMF_TIMER_PFCP_NO_ESTABLISHMENT_RESPONSE,
SMF_TIMER_PFCP_NO_DELETION_RESPONSE,
MAX_NUM_OF_SMF_TIMER,

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019-2023 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -69,7 +69,8 @@ void upf_n4_handle_session_establishment_request(
if (!sess) {
ogs_error("No Context");
ogs_pfcp_send_error_message(xact, 0,
ogs_pfcp_send_error_message(xact,
OGS_PFCP_SEID_NO_PRESENCE, 0,
OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE,
OGS_PFCP_CAUSE_MANDATORY_IE_MISSING, 0);
upf_metrics_inst_by_cause_add(OGS_PFCP_CAUSE_MANDATORY_IE_MISSING,
@ -214,7 +215,9 @@ cleanup:
upf_metrics_inst_by_cause_add(cause_value,
UPF_METR_CTR_SM_N4SESSIONESTABFAIL, 1);
ogs_pfcp_sess_clear(&sess->pfcp);
ogs_pfcp_send_error_message(xact, sess ? sess->smf_n4_f_seid.seid : 0,
ogs_pfcp_send_error_message(xact,
sess ? OGS_PFCP_SEID_PRESENCE : OGS_PFCP_SEID_NO_PRESENCE,
sess ? sess->smf_n4_f_seid.seid : 0,
OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE,
cause_value, offending_ie_value);
}
@ -240,7 +243,8 @@ void upf_n4_handle_session_modification_request(
if (!sess) {
ogs_error("No Context");
ogs_pfcp_send_error_message(xact, 0,
ogs_pfcp_send_error_message(xact,
OGS_PFCP_SEID_NO_PRESENCE, 0,
OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE,
OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND, 0);
return;
@ -413,7 +417,9 @@ void upf_n4_handle_session_modification_request(
cleanup:
ogs_pfcp_sess_clear(&sess->pfcp);
ogs_pfcp_send_error_message(xact, sess ? sess->smf_n4_f_seid.seid : 0,
ogs_pfcp_send_error_message(xact,
sess ? OGS_PFCP_SEID_PRESENCE : OGS_PFCP_SEID_NO_PRESENCE,
sess ? sess->smf_n4_f_seid.seid : 0,
OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE,
cause_value, offending_ie_value);
}
@ -431,7 +437,8 @@ void upf_n4_handle_session_deletion_request(
if (!sess) {
ogs_error("No Context");
ogs_pfcp_send_error_message(xact, 0,
ogs_pfcp_send_error_message(xact,
OGS_PFCP_SEID_NO_PRESENCE, 0,
OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE,
OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND, 0);
return;

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -183,6 +183,7 @@ int upf_pfcp_send_session_establishment_response(
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_ESTABLISHMENT_RESPONSE_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->smf_n4_f_seid.seid;
n4buf = upf_n4_build_session_establishment_response(
@ -216,6 +217,7 @@ int upf_pfcp_send_session_modification_response(
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_MODIFICATION_RESPONSE_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->smf_n4_f_seid.seid;
n4buf = upf_n4_build_session_modification_response(
@ -248,6 +250,7 @@ int upf_pfcp_send_session_deletion_response(ogs_pfcp_xact_t *xact,
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_DELETION_RESPONSE_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->smf_n4_f_seid.seid;
n4buf = upf_n4_build_session_deletion_response(h.type, sess);
@ -300,6 +303,7 @@ int upf_pfcp_send_session_report_request(
memset(&h, 0, sizeof(ogs_pfcp_header_t));
h.type = OGS_PFCP_SESSION_REPORT_REQUEST_TYPE;
h.seid_presence = OGS_PFCP_SEID_PRESENCE;
h.seid = sess->smf_n4_f_seid.seid;
xact = ogs_pfcp_xact_local_create(sess->pfcp_node, sess_timeout, sess);

View File

@ -322,10 +322,6 @@ void upf_pfcp_state_associated(ogs_fsm_t *s, upf_event_t *e)
}
break;
case UPF_EVT_N4_NO_HEARTBEAT:
/* 'node' context was removed in ogs_pfcp_xact_delete(xact)
* So, we should not use PFCP node here */
ogs_warn("No Heartbeat from SMF [%s]:%d",
OGS_ADDR(addr, buf), OGS_PORT(addr));
OGS_FSM_TRAN(s, upf_pfcp_state_will_associate);

View File

@ -470,11 +470,84 @@ static void test2_func(abts_case *tc, void *data)
rv = testvlr_sgsap_send(sgsap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Attach Reject */
/* Receive Initial Context Setup Request +
* Attach Accept +
* Activate Default Bearer Context Request */
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send Initial Context Setup Response */
sendbuf = test_s1ap_build_initial_context_setup_response(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Attach Complete + Activate default EPS bearer cotext accept */
test_ue->nr_cgi.cell_id = 0x1234502;
bearer = test_bearer_find_by_ue_ebi(test_ue, 5);
ogs_assert(bearer);
esmbuf = testesm_build_activate_default_eps_bearer_context_accept(
bearer, false);
ABTS_PTR_NOTNULL(tc, esmbuf);
emmbuf = testemm_build_attach_complete(test_ue, esmbuf);
ABTS_PTR_NOTNULL(tc, emmbuf);
sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive EMM information */
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send UE Context Release Request */
sendbuf = test_s1ap_build_ue_context_release_request(test_ue,
S1AP_Cause_PR_radioNetwork, S1AP_CauseRadioNetwork_user_inactivity);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive UE Context Release Command */
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send UE Context Release Complete */
sendbuf = test_s1ap_build_ue_context_release_complete(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Service Request */
emmbuf = testemm_build_service_request(test_ue);
ABTS_PTR_NOTNULL(tc, emmbuf);
sendbuf = test_s1ap_build_initial_ue_message(
test_ue, emmbuf, S1AP_RRC_Establishment_Cause_mo_Data, true);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Initial Context Setup Request */
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
tests1ap_recv(test_ue, recvbuf);
/* Send Initial Context Setup Response */
sendbuf = test_s1ap_build_initial_context_setup_response(test_ue);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Detach Request */
emmbuf = testemm_build_detach_request(test_ue, 1, true, true);
ABTS_PTR_NOTNULL(tc, emmbuf);
sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf);
ABTS_PTR_NOTNULL(tc, sendbuf);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive UE Context Release Command */
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019,2020 by Sukchan Lee <acetcom@gmail.com>
* Copyright (C) 2019-2024 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
@ -135,6 +135,7 @@ int test_s2b_send_create_session_request(test_sess_t *sess, bool handover_ind)
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_CREATE_SESSION_REQUEST_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sess->smf_s2b_c_teid;
pkbuf = test_s2b_build_create_session_request(h.type, sess, handover_ind);
@ -166,6 +167,7 @@ int test_s2b_send_delete_session_request(test_sess_t *sess)
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_DELETE_SESSION_REQUEST_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sess->smf_s2b_c_teid;
pkbuf = test_s2b_build_delete_session_request(h.type, sess);
@ -201,6 +203,7 @@ int test_s2b_send_create_bearer_response(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_CREATE_BEARER_RESPONSE_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sess->smf_s2b_c_teid;
pkbuf = test_s2b_build_create_bearer_response(h.type, bearer);
@ -236,6 +239,7 @@ int test_s2b_send_delete_bearer_response(
memset(&h, 0, sizeof(ogs_gtp2_header_t));
h.type = OGS_GTP2_DELETE_BEARER_RESPONSE_TYPE;
h.teid_presence = OGS_GTP2_TEID_PRESENCE;
h.teid = sess->smf_s2b_c_teid;
pkbuf = test_s2b_build_delete_bearer_response(h.type, bearer);