Fix PCRF Session Control (#195)

- If PCRF Session is NULL and CC-Request-Type is Terminate,
   the result code is DIAMETER_UNKNOWN_SESSION_ID
This commit is contained in:
Sukchan Lee 2019-06-14 16:55:16 +09:00
parent 9e3ebf9a16
commit d3476eca6d
3 changed files with 109 additions and 97 deletions

View File

@ -40,7 +40,6 @@ struct rx_sess_state {
struct sess_state {
os0_t sid; /* Gx Session-Id */
uint32_t cc_request_type; /* CC-Request-Type */
os0_t peer_host; /* Peer Host */
char *imsi_bcd;
@ -201,16 +200,97 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp,
gx_message_t gx_message;
uint32_t cc_request_type = GX_CC_REQUEST_TYPE_INITIAL_REQUEST;
uint32_t cc_request_number = 0;
uint32_t result_code = FD_DIAMETER_MISSING_AVP;
ogs_debug("[PCRF] Credit-Control-Request");
ogs_debug("[Credit-Control-Request]");
ogs_assert(msg);
/* Initialize Message */
memset(&gx_message, 0, sizeof(gx_message_t));
/* Create answer header */
qry = *msg;
ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0);
ogs_assert(ret == 0);
ans = *msg;
/* Set the Auth-Application-Id AVP */
ret = fd_msg_avp_new(fd_auth_application_id, 0, &avp);
ogs_assert(ret == 0);
val.i32 = GX_APPLICATION_ID;
ret = fd_msg_avp_setvalue(avp, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
ogs_assert(ret == 0);
/* Get CC-Request-Type */
ret = fd_msg_search_avp(qry, gx_cc_request_type, &avp);
ogs_assert(ret == 0);
if (avp) {
ret = fd_msg_avp_hdr(avp, &hdr);
ogs_assert(ret == 0);
cc_request_type = hdr->avp_value->i32;
} else {
ogs_error("no_CC-Request-Type ");
ogs_assert_if_reached();
}
/* Get CC-Request-Number */
ret = fd_msg_search_avp(qry, gx_cc_request_number, &avp);
ogs_assert(ret == 0);
if (avp) {
ret = fd_msg_avp_hdr(avp, &hdr);
ogs_assert(ret == 0);
cc_request_number = hdr->avp_value->i32;
} else {
ogs_error("no_CC-Request-Number");
ogs_assert_if_reached();
}
ogs_debug(" CC-Request-Type[%d] Number[%d]",
cc_request_type, cc_request_number);
/* Set CC-Request-Type */
ret = fd_msg_avp_new(gx_cc_request_type, 0, &avp);
ogs_assert(ret == 0);
val.i32 = cc_request_type;
ret = fd_msg_avp_setvalue(avp, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
ogs_assert(ret == 0);
/* Set CC-Request-Number */
ret = fd_msg_avp_new(gx_cc_request_number, 0, &avp);
ogs_assert(ret == 0);
val.i32 = cc_request_number;
ret = fd_msg_avp_setvalue(avp, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
ogs_assert(ret == 0);
/* Find Session */
ret = fd_sess_state_retrieve(pcrf_gx_reg, sess, &sess_data);
ogs_assert(ret == 0);
/* Check Session */
if (!sess_data &&
(cc_request_type == GX_CC_REQUEST_TYPE_UPDATE_REQUEST ||
cc_request_type == GX_CC_REQUEST_TYPE_TERMINATION_REQUEST))
{
ogs_warn("No Session for CC-Request-Type: [%d]", cc_request_type);
result_code = FD_DIAMETER_MISSING_AVP;
ret = fd_msg_rescode_set(ans,
"DIAMETER_UNKNOWN_SESSION_ID", NULL, NULL, 1);
ogs_assert(ret == 0);
ret = fd_msg_send(msg, NULL, NULL);
ogs_assert(ret == 0);
return 0;
}
if (!sess_data) {
os0_t sid;
size_t sidlen;
@ -222,15 +302,6 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp,
ogs_assert(sess_data);
}
/* Initialize Message */
memset(&gx_message, 0, sizeof(gx_message_t));
/* Create answer header */
qry = *msg;
ret = fd_msg_new_answer_from_req(fd_g_config->cnf_dict, msg, 0);
ogs_assert(ret == 0);
ans = *msg;
/* Get Origin-Host */
ret = fd_msg_search_avp(qry, fd_origin_host, &avp);
ogs_assert(ret == 0);
@ -249,28 +320,6 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp,
goto out;
}
/* Get CC-Request-Type */
ret = fd_msg_search_avp(qry, gx_cc_request_type, &avp);
ogs_assert(ret == 0);
if (avp) {
ret = fd_msg_avp_hdr(avp, &hdr);
ogs_assert(ret == 0);
sess_data->cc_request_type = hdr->avp_value->i32;
} else {
ogs_error("no_CC-Request-Type ");
result_code = FD_DIAMETER_MISSING_AVP;
goto out;
}
/* Get CC-Request-Number */
ret = fd_msg_search_avp(qry, gx_cc_request_number, &avp);
ogs_assert(ret == 0);
if (avp) {
ret = fd_msg_avp_hdr(avp, &hdr);
ogs_assert(ret == 0);
cc_request_number = hdr->avp_value->i32;
}
/* Get Framed-IP-Address */
ret = fd_msg_search_avp(qry, gx_framed_ip_address, &avp);
ogs_assert(ret == 0);
@ -301,33 +350,6 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp,
sess_data->ipv6 = 1;
}
/* Set the Auth-Application-Id AVP */
ret = fd_msg_avp_new(fd_auth_application_id, 0, &avp);
ogs_assert(ret == 0);
val.i32 = GX_APPLICATION_ID;
ret = fd_msg_avp_setvalue(avp, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
ogs_assert(ret == 0);
/* Set CC-Request-Type */
ret = fd_msg_avp_new(gx_cc_request_type, 0, &avp);
ogs_assert(ret == 0);
val.i32 = sess_data->cc_request_type;
ret = fd_msg_avp_setvalue(avp, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
ogs_assert(ret == 0);
/* Set CC-Request-Number */
ret = fd_msg_avp_new(gx_cc_request_number, 0, &avp);
ogs_assert(ret == 0);
val.i32 = cc_request_number;
ret = fd_msg_avp_setvalue(avp, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
ogs_assert(ret == 0);
/* Get IMSI + APN */
ret = fd_msg_search_avp(qry, gx_subscription_id, &avp);
ogs_assert(ret == 0);
@ -398,8 +420,8 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp,
goto out;
}
if (sess_data->cc_request_type == GX_CC_REQUEST_TYPE_INITIAL_REQUEST ||
sess_data->cc_request_type == GX_CC_REQUEST_TYPE_UPDATE_REQUEST) {
if (cc_request_type == GX_CC_REQUEST_TYPE_INITIAL_REQUEST ||
cc_request_type == GX_CC_REQUEST_TYPE_UPDATE_REQUEST) {
int charging_rule = 0;
for (i = 0; i < gx_message.num_of_pcc_rule; i++) {
@ -520,8 +542,7 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp,
ret = fd_msg_avp_add(ans, MSG_BRW_LAST_CHILD, avp);
ogs_assert(ret == 0);
} else if (sess_data->cc_request_type ==
GX_CC_REQUEST_TYPE_TERMINATION_REQUEST) {
} else if (cc_request_type == GX_CC_REQUEST_TYPE_TERMINATION_REQUEST) {
struct rx_sess_state *rx_sess_data = NULL, *next_rx_sess_data = NULL;
ogs_list_for_each_safe(&sess_data->rx_list,
next_rx_sess_data, rx_sess_data) {
@ -537,7 +558,7 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp,
ret = fd_msg_rescode_set(ans, "DIAMETER_SUCCESS", NULL, NULL, 1);
ogs_assert(ret == 0);
if (sess_data->cc_request_type != GX_CC_REQUEST_TYPE_TERMINATION_REQUEST) {
if (cc_request_type != GX_CC_REQUEST_TYPE_TERMINATION_REQUEST) {
/* Store this value in the session */
ret = fd_sess_state_store(pcrf_gx_reg, sess, &sess_data);
ogs_assert(ret == 0);
@ -550,7 +571,7 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp,
ret = fd_msg_send(msg, NULL, NULL);
ogs_assert(ret == 0);
ogs_debug("[PCRF] Credit-Control-Answer");
ogs_debug("[Credit-Control-Answer]");
/* Add this value to the stats */
ogs_assert(pthread_mutex_lock(&fd_logger_self()->stats_lock) == 0);
@ -580,7 +601,7 @@ out:
ogs_assert(ret == 0);
}
if (sess_data->cc_request_type != GX_CC_REQUEST_TYPE_TERMINATION_REQUEST) {
if (cc_request_type != GX_CC_REQUEST_TYPE_TERMINATION_REQUEST) {
/* Store this value in the session */
ret = fd_sess_state_store(pcrf_gx_reg, sess, &sess_data);
ogs_assert(sess_data == NULL);

View File

@ -780,12 +780,12 @@ out:
(int)(ts.tv_sec + 1 - sess_data->ts.tv_sec),
(long)(1000000000 + ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
ogs_debug(" [LAST] CC-Request-Type[%d] Number[%d] in Session Data",
ogs_debug(" CC-Request-Type[%d] Number[%d] in Session Data",
sess_data->cc_request_type, sess_data->cc_request_number);
ogs_debug(" Current CC-Request-Number[%d]", cc_request_number);
ogs_debug(" Current CC-Request-Number[%d]", cc_request_number);
if (sess_data->cc_request_type == GX_CC_REQUEST_TYPE_TERMINATION_REQUEST &&
sess_data->cc_request_number <= cc_request_number) {
ogs_debug(" state_cleanup(): [%s]", sess_data->gx_sid);
ogs_debug(" [LAST] state_cleanup(): [%s]", sess_data->gx_sid);
state_cleanup(sess_data, NULL, NULL);
} else {
ogs_debug(" fd_sess_state_store(): [%s]", sess_data->gx_sid);

View File

@ -174,34 +174,25 @@ void pgw_state_operational(ogs_fsm_t *s, pgw_event_t *e)
ogs_assert(gtpbuf);
message = gtpbuf->data;
if (!sess) {
ogs_error("No Session");
ogs_pkbuf_free(gtpbuf);
break;
}
if (gx_message->result_code != ER_DIAMETER_SUCCESS) {
if (gx_message->result_code == ER_DIAMETER_SUCCESS) {
switch(gx_message->cc_request_type) {
case GX_CC_REQUEST_TYPE_INITIAL_REQUEST:
pgw_gx_handle_cca_initial_request(
sess, gx_message, xact,
&message->create_session_request);
break;
case 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);
ogs_pkbuf_free(gtpbuf);
break;
}
switch(gx_message->cc_request_type) {
case GX_CC_REQUEST_TYPE_INITIAL_REQUEST:
pgw_gx_handle_cca_initial_request(
sess, gx_message, xact,
&message->create_session_request);
break;
case 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;
}
ogs_pkbuf_free(gtpbuf);
break;