Compare commits

...

2 Commits

Author SHA1 Message Date
Pau Espin c06303ec54 [SMF] Handle APCO IE in S2b GTPv2C CreateSessionRequest/Response
This IE is used by UEs registering through S2b interface (ePDG) to
obtain DNS and P-CSCF server address information.
2024-02-26 16:49:51 +01:00
Pau Espin 5b1edb816a [SMF] Setup Gy session when creating UE session over S2b interface
So far the Gy session creation triggered by S2b interface (ePDG) was not
implemented. Fix it.
2024-02-26 16:49:44 +01:00
7 changed files with 82 additions and 14 deletions

View File

@ -1,4 +1,4 @@
/*
/* 3GPP TS 29.273 section 9
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
@ -35,7 +35,8 @@ extern struct dict_object *ogs_diam_s6b_application;
extern struct dict_object *ogs_diam_s6b_mip6_feature_vector;
typedef struct ogs_diam_s6b_message_s {
#define OGS_DIAM_S6B_CMD_SESSION_TERMINATION 1
#define OGS_DIAM_S6B_CMD_AUTHENTICATION_AUTHORIZATION 1
#define OGS_DIAM_S6B_CMD_SESSION_TERMINATION 2
uint16_t cmd_code;
uint32_t result_code;
uint32_t *err;

View File

@ -228,6 +228,8 @@ typedef struct smf_sess_s {
uint32_t gx_cca_init_err; /* Gx CCA RXed error code */
bool gy_ccr_init_in_flight; /* Waiting for Gy CCA */
uint32_t gy_cca_init_err; /* Gy CCA RXed error code */
bool s6b_aar_in_flight; /* Waiting for S6B AAR */
uint32_t s6b_aaa_err; /* S6B AAA RXed error code */
bool gx_ccr_term_in_flight; /* Waiting for Gx CCA */
uint32_t gx_cca_term_err; /* Gx CCA RXed error code */
bool gy_ccr_term_in_flight; /* Waiting for Gy CCA */
@ -333,6 +335,7 @@ typedef struct smf_sess_s {
struct {
uint8_t version; /* GTPC version */
ogs_tlv_octet_t ue_pco;
ogs_tlv_octet_t ue_apco;
ogs_tlv_octet_t ue_epco;
ogs_tlv_octet_t user_location_information;
ogs_tlv_octet_t ue_timezone;

View File

@ -182,8 +182,10 @@ void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e)
switch (e->h.id) {
case OGS_FSM_ENTRY_SIG:
/* reset state: */
sess->sm_data.s6b_aar_in_flight = false;
sess->sm_data.gx_ccr_init_in_flight = false;
sess->sm_data.gy_ccr_init_in_flight = false;
sess->sm_data.s6b_aaa_err = ER_DIAMETER_SUCCESS;
sess->sm_data.gx_cca_init_err = ER_DIAMETER_SUCCESS;
sess->sm_data.gy_cca_init_err = ER_DIAMETER_SUCCESS;
break;
@ -229,7 +231,9 @@ void smf_gsm_state_initial(ogs_fsm_t *s, smf_event_t *e)
break;
case OGS_GTP2_RAT_TYPE_WLAN:
smf_s6b_send_aar(sess, e->gtp_xact);
sess->sm_data.s6b_aar_in_flight = true;
OGS_FSM_TRAN(s, smf_gsm_state_wait_epc_auth_initial);
/* Gx/Gy Init Req is done after s6b AAR + AAA */
break;
default:
ogs_error("Unknown RAT Type [%d]", sess->gtp_rat_type);
@ -327,6 +331,7 @@ void smf_gsm_state_wait_epc_auth_initial(ogs_fsm_t *s, smf_event_t *e)
{
smf_sess_t *sess = NULL;
ogs_diam_s6b_message_t *s6b_message = NULL;
ogs_diam_gy_message_t *gy_message = NULL;
ogs_diam_gx_message_t *gx_message = NULL;
uint32_t diam_err;
@ -340,6 +345,22 @@ void smf_gsm_state_wait_epc_auth_initial(ogs_fsm_t *s, smf_event_t *e)
ogs_assert(sess);
switch (e->h.id) {
case SMF_EVT_S6B_MESSAGE:
s6b_message = e->s6b_message;
ogs_assert(s6b_message);
switch(s6b_message->cmd_code) {
case OGS_DIAM_S6B_CMD_AUTHENTICATION_AUTHORIZATION:
sess->sm_data.s6b_aar_in_flight = false;
sess->sm_data.s6b_aaa_err = s6b_message->result_code;
if (s6b_message->result_code == ER_DIAMETER_SUCCESS) {
send_ccr_init_req_gx_gy(sess, e);
return;
}
goto test_can_proceed;
}
break;
case SMF_EVT_GX_MESSAGE:
gx_message = e->gx_message;
ogs_assert(gx_message);
@ -382,9 +403,12 @@ void smf_gsm_state_wait_epc_auth_initial(ogs_fsm_t *s, smf_event_t *e)
test_can_proceed:
/* First wait for both Gx and Gy requests to be done: */
if (!sess->sm_data.gx_ccr_init_in_flight &&
if (!sess->sm_data.s6b_aar_in_flight &&
!sess->sm_data.gx_ccr_init_in_flight &&
!sess->sm_data.gy_ccr_init_in_flight) {
diam_err = ER_DIAMETER_SUCCESS;
if (sess->sm_data.s6b_aaa_err != ER_DIAMETER_SUCCESS)
diam_err = sess->sm_data.s6b_aaa_err;
if (sess->sm_data.gx_cca_init_err != ER_DIAMETER_SUCCESS)
diam_err = sess->sm_data.gx_cca_init_err;
if (sess->sm_data.gy_cca_init_err != ER_DIAMETER_SUCCESS)

View File

@ -47,6 +47,8 @@ ogs_pkbuf_t *smf_s5c_build_create_session_response(
int len;
uint8_t pco_buf[OGS_MAX_PCO_LEN];
int16_t pco_len;
uint8_t apco_buf[OGS_MAX_PCO_LEN];
int16_t apco_len;
uint8_t *epco_buf = NULL;
int16_t epco_len;
@ -145,6 +147,17 @@ ogs_pkbuf_t *smf_s5c_build_create_session_response(
rsp->protocol_configuration_options.len = pco_len;
}
/* APCO */
if (sess->gtp.ue_apco.presence &&
sess->gtp.ue_apco.len && sess->gtp.ue_apco.data) {
apco_len = smf_pco_build(
apco_buf, sess->gtp.ue_apco.data, sess->gtp.ue_apco.len);
ogs_assert(apco_len > 0);
rsp->additional_protocol_configuration_options.presence = 1;
rsp->additional_protocol_configuration_options.data = apco_buf;
rsp->additional_protocol_configuration_options.len = apco_len;
}
/* ePCO */
if (sess->gtp.ue_epco.presence &&
sess->gtp.ue_epco.len && sess->gtp.ue_epco.data) {

View File

@ -378,6 +378,12 @@ uint8_t smf_s5c_handle_create_session_request(
&req->protocol_configuration_options);
}
/* APCO */
if (req->additional_protocol_configuration_options.presence) {
OGS_TLV_STORE_DATA(&sess->gtp.ue_apco,
&req->additional_protocol_configuration_options);
}
/* Set User Location Information */
if (req->user_location_information.presence) {
OGS_TLV_STORE_DATA(&sess->gtp.user_location_information,
@ -452,6 +458,8 @@ uint8_t smf_s5c_handle_delete_session_request(
OGS_TLV_CLEAR_DATA(&sess->gtp.ue_pco);
}
/* APCO not present in Session deletion procedure, hence no need to clear it here. */
if (req->extended_protocol_configuration_options.presence) {
OGS_TLV_STORE_DATA(&sess->gtp.ue_epco,
&req->extended_protocol_configuration_options);

View File

@ -1,4 +1,4 @@
/*
/* 3GPP TS 29.273 section 9
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
@ -344,11 +344,11 @@ static void smf_s6b_aaa_cb(void *data, struct msg **msg)
unsigned long dur;
int error = 0;
int new;
int result_code = 0;
int exp_result_code = 0;
smf_sess_t *sess = NULL;
ogs_gtp_xact_t *xact = NULL;
smf_event_t *e = NULL;
ogs_diam_s6b_message_t *s6b_message = NULL;
ogs_debug("[AA-Answer]");
@ -374,15 +374,20 @@ static void smf_s6b_aaa_cb(void *data, struct msg **msg)
xact = sess_data->xact;
ogs_assert(xact);
s6b_message = ogs_calloc(1, sizeof(ogs_diam_s6b_message_t));
ogs_assert(s6b_message);
/* Set Session Termination Command */
s6b_message->cmd_code = OGS_DIAM_S6B_CMD_AUTHENTICATION_AUTHORIZATION;
/* Value of Result Code */
ret = fd_msg_search_avp(*msg, ogs_diam_result_code, &avp);
ogs_assert(ret == 0);
if (avp) {
ret = fd_msg_avp_hdr(avp, &hdr);
ogs_assert(ret == 0);
result_code = hdr->avp_value->i32;
if (result_code != ER_DIAMETER_SUCCESS) {
ogs_error("Result Code: %d", result_code);
s6b_message->result_code = hdr->avp_value->i32;
if (s6b_message->result_code != ER_DIAMETER_SUCCESS) {
ogs_error("Result Code: %d", s6b_message->result_code);
error++;
}
} else {
@ -397,8 +402,8 @@ static void smf_s6b_aaa_cb(void *data, struct msg **msg)
if (avpch1) {
ret = fd_msg_avp_hdr(avpch1, &hdr);
ogs_assert(ret == 0);
exp_result_code = hdr->avp_value->i32;
ogs_error("Experimental Result Code: %d", exp_result_code);
s6b_message->result_code = hdr->avp_value->i32;
ogs_error("Experimental Result Code: %d", s6b_message->result_code);
}
} else {
ogs_error("no Result-Code");
@ -431,9 +436,22 @@ static void smf_s6b_aaa_cb(void *data, struct msg **msg)
error++;
}
if (!error) {
smf_gx_send_ccr(sess, xact,
OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST);
e = smf_event_new(SMF_EVT_S6B_MESSAGE);
ogs_assert(e);
if (error && s6b_message->result_code == ER_DIAMETER_SUCCESS)
s6b_message->result_code = error;
e->sess = sess;
e->gtp_xact = xact;
e->s6b_message = s6b_message;
ret = ogs_queue_push(ogs_app()->queue, e);
if (ret != OGS_OK) {
ogs_error("ogs_queue_push() failed:%d", (int)ret);
ogs_free(s6b_message);
ogs_event_free(e);
} else {
ogs_pollset_notify(ogs_app()->pollset);
}
/* Free the message */

View File

@ -365,6 +365,7 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e)
ogs_assert(sess);
switch(s6b_message->cmd_code) {
case OGS_DIAM_S6B_CMD_AUTHENTICATION_AUTHORIZATION:
case OGS_DIAM_S6B_CMD_SESSION_TERMINATION:
ogs_fsm_dispatch(&sess->sm, e);
break;