P-GW respond to DIAMETER error from PCRF(#403)

This commit is contained in:
Sukchan Lee 2020-04-18 13:07:06 -04:00
parent 63809a3677
commit 5009876c16
5 changed files with 61 additions and 20 deletions

View File

@ -146,6 +146,8 @@ typedef struct ogs_diam_gx_message_s {
#define OGS_DIAM_GX_DIAMETER_ADC_RULE_EVENT 5148
#define OGS_DIAM_GX_DIAMETER_ERROR_NBIFOM_NOT_AUTHORIZED 5149
uint32_t result_code;
uint32_t *err;
uint32_t *exp_err;
#define OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST 1
#define OGS_DIAM_GX_CC_REQUEST_TYPE_UPDATE_REQUEST 2

View File

@ -67,7 +67,6 @@ static uint8_t emm_cause_from_diameter(
case ER_DIAMETER_MISSING_AVP: /* 5005 */
case ER_DIAMETER_RESOURCES_EXCEEDED: /* 5006 */
case ER_DIAMETER_AVP_OCCURS_TOO_MANY_TIMES: /* 5009 */
default: /* FIXME: only permanent */
return EMM_CAUSE_NETWORK_FAILURE;
}
}

View File

@ -530,6 +530,7 @@ static void pgw_gx_cca_cb(void *data, struct msg **msg)
ret = fd_msg_avp_hdr(avp, &hdr);
ogs_assert(ret == 0);
gx_message->result_code = hdr->avp_value->i32;
gx_message->err = &gx_message->result_code;
ogs_debug(" Result Code: %d", hdr->avp_value->i32);
} else {
ret = fd_msg_search_avp(*msg, ogs_diam_experimental_result, &avp);
@ -541,6 +542,7 @@ static void pgw_gx_cca_cb(void *data, struct msg **msg)
ret = fd_msg_avp_hdr(avpch1, &hdr);
ogs_assert(ret == 0);
gx_message->result_code = hdr->avp_value->i32;
gx_message->exp_err = &gx_message->result_code;
ogs_debug(" Experimental Result Code: %d",
gx_message->result_code);
}

View File

@ -42,6 +42,24 @@ static void timeout(ogs_gtp_xact_t *xact, void *data)
"Message-Type[%d]", sess->sgw_s5c_teid, sess->pgw_s5c_teid, type);
}
static uint8_t gtp_cause_from_diameter(
const uint32_t *dia_err, const uint32_t *dia_exp_err)
{
if (dia_exp_err) {
}
if (dia_err) {
switch (*dia_err) {
case OGS_DIAM_UNKNOWN_SESSION_ID:
return OGS_GTP_CAUSE_APN_ACCESS_DENIED_NO_SUBSCRIPTION;
}
}
ogs_error("Unexpected Diameter Result Code %d/%d, defaulting to severe "
"network failure",
dia_err ? *dia_err : -1, dia_exp_err ? *dia_exp_err : -1);
return OGS_GTP_CAUSE_UE_NOT_AUTHORISED_BY_OCS_OR_EXTERNAL_AAA_SERVER;
}
void pgw_gx_handle_cca_initial_request(
pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message,
ogs_gtp_xact_t *xact, ogs_gtp_create_session_request_t *req)
@ -55,6 +73,19 @@ void pgw_gx_handle_cca_initial_request(
ogs_assert(xact);
ogs_assert(req);
ogs_debug("[PGW] Create Session Response");
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
if (gx_message->result_code != ER_DIAMETER_SUCCESS) {
uint8_t cause_value = gtp_cause_from_diameter(
gx_message->err, gx_message->exp_err);
ogs_gtp_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0,
OGS_GTP_CREATE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
/* Send Create Session Request with Creating Default Bearer */
memset(&h, 0, sizeof(ogs_gtp_header_t));
h.type = OGS_GTP_CREATE_SESSION_RESPONSE_TYPE;
@ -97,6 +128,15 @@ void pgw_gx_handle_cca_termination_request(
/* Remove a pgw session */
pgw_sess_remove(sess);
if (gx_message->result_code != ER_DIAMETER_SUCCESS) {
uint8_t cause_value = gtp_cause_from_diameter(
gx_message->err, gx_message->exp_err);
ogs_gtp_send_error_message(xact, sgw_s5c_teid,
OGS_GTP_DELETE_SESSION_RESPONSE_TYPE, cause_value);
return;
}
memset(&h, 0, sizeof(ogs_gtp_header_t));
h.type = OGS_GTP_DELETE_SESSION_RESPONSE_TYPE;
h.teid = sgw_s5c_teid;

View File

@ -199,26 +199,24 @@ void pgw_state_operational(ogs_fsm_t *s, pgw_event_t *e)
gtpbuf = e->gtpbuf;
ogs_assert(gtpbuf);
message = (ogs_gtp_message_t *)gtpbuf->data;
ogs_assert(message);
if (gx_message->result_code == ER_DIAMETER_SUCCESS) {
switch(gx_message->cc_request_type) {
case OGS_DIAM_GX_CC_REQUEST_TYPE_INITIAL_REQUEST:
pgw_gx_handle_cca_initial_request(
sess, gx_message, xact,
&message->create_session_request);
break;
case OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST:
pgw_gx_handle_cca_termination_request(
sess, gx_message, xact,
&message->delete_session_request);
break;
default:
ogs_error("Not implemented(%d)",
gx_message->cc_request_type);
break;
}
} else
ogs_error("Diameter Error(%d)", gx_message->result_code);
switch(message->h.type) {
case OGS_GTP_CREATE_SESSION_REQUEST_TYPE:
pgw_gx_handle_cca_initial_request(
sess, gx_message, xact,
&message->create_session_request);
break;
case OGS_GTP_DELETE_SESSION_REQUEST_TYPE:
pgw_gx_handle_cca_termination_request(
sess, gx_message, xact,
&message->delete_session_request);
break;
default:
ogs_error("Not implemented(%d)",
gx_message->cc_request_type);
break;
}
ogs_pkbuf_free(gtpbuf);
break;