forked from acouzens/open5gs
GX-CCR message build done
This commit is contained in:
parent
17dc308aa2
commit
0e7196c9c1
|
@ -58,7 +58,7 @@ c_int16_t apn_build(c_int8_t *dst, c_int8_t *src, c_int16_t len)
|
|||
|
||||
c_int16_t apn_parse(c_int8_t *dst, c_int8_t *src, c_int16_t len)
|
||||
{
|
||||
core_cpystrn(dst, src+1, c_min(len, MAX_APN_LEN)+1);
|
||||
core_cpystrn(dst, src+1, c_min(len-1, MAX_APN_LEN)+1);
|
||||
|
||||
return len-1;
|
||||
}
|
||||
|
|
|
@ -97,6 +97,7 @@ CORE_DECLARE(void *) core_uint64_to_buffer(
|
|||
CORE_DECLARE(c_uint64_t) core_buffer_to_uint64(void *buffer, int size);
|
||||
|
||||
CORE_DECLARE(void *) core_bcd_to_buffer(c_int8_t *in, void *out, int *out_len);
|
||||
CORE_DECLARE(void *) core_buffer_to_bcd(c_uint8_t *in, int in_len, void *out);
|
||||
|
||||
/*
|
||||
* Apache's "replacement" for the strncpy() function. We roll our
|
||||
|
|
|
@ -86,6 +86,30 @@ void *core_bcd_to_buffer(c_int8_t *in, void *out, int *out_len)
|
|||
}
|
||||
|
||||
*out_len = (in_len + 1) / 2;
|
||||
if (in_len & 0x01)
|
||||
{
|
||||
out_p[(*out_len)-1] |= 0xF0;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void *core_buffer_to_bcd(c_uint8_t *in, int in_len, void *out)
|
||||
{
|
||||
int i = 0;
|
||||
c_uint8_t *out_p = out;
|
||||
|
||||
for (i = 0; i < in_len; i++)
|
||||
{
|
||||
out_p[i*2] = 0x30 + (in[i] & 0x0F);
|
||||
out_p[i*2+1] = 0x30 + ((in[i] & 0xF0) >> 4);
|
||||
}
|
||||
|
||||
out_p[in_len*2] = 0;
|
||||
if ((out_p[in_len*2-1] & 0x0F) == 0x0F)
|
||||
{
|
||||
out_p[in_len*2-1] = 0;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
|
|
@ -113,6 +113,28 @@ static void misc_test6(abts_case *tc, void *data)
|
|||
core_bcd_to_buffer(MEI, out, &out_len);
|
||||
ABTS_TRUE(tc,
|
||||
memcmp("\x53\x61\x20\x00\x91\x78\x84\x00", out, out_len) == 0);
|
||||
#define IMSI "001010123456819"
|
||||
core_bcd_to_buffer(IMSI, out, &out_len);
|
||||
ABTS_TRUE(tc,
|
||||
memcmp("\x00\x01\x01\x21\x43\x65\x18\xf9", out, out_len) == 0);
|
||||
}
|
||||
|
||||
static void misc_test7(abts_case *tc, void *data)
|
||||
{
|
||||
char out[32];
|
||||
c_uint8_t buf1[6] = "\x94\x71\x52\x76\x00\x41";
|
||||
int buf1_len = 6;
|
||||
c_uint8_t buf2[8] = "\x53\x61\x20\x00\x91\x78\x84\x00";
|
||||
int buf2_len = 8;
|
||||
c_uint8_t buf3[8] = "\x00\x01\x01\x21\x43\x65\x18\xf9";
|
||||
int buf3_len = 8;
|
||||
|
||||
core_buffer_to_bcd(buf1, buf1_len, out);
|
||||
ABTS_TRUE(tc, strcmp("491725670014", out) == 0);
|
||||
core_buffer_to_bcd(buf2, buf2_len, out);
|
||||
ABTS_TRUE(tc, strcmp("3516020019874800", out) == 0);
|
||||
core_buffer_to_bcd(buf3, buf3_len, out);
|
||||
ABTS_TRUE(tc, strcmp("001010123456819", out) == 0);
|
||||
}
|
||||
|
||||
abts_suite *testmisc(abts_suite *suite)
|
||||
|
@ -125,6 +147,7 @@ abts_suite *testmisc(abts_suite *suite)
|
|||
abts_run_test(suite, misc_test4, NULL);
|
||||
abts_run_test(suite, misc_test5, NULL);
|
||||
abts_run_test(suite, misc_test6, NULL);
|
||||
abts_run_test(suite, misc_test7, NULL);
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
|
|
@ -12,12 +12,27 @@ struct dict_object *gx_cc_request_type = NULL;
|
|||
struct dict_object *gx_cc_request_number = NULL;
|
||||
struct dict_object *gx_network_request_support = NULL;
|
||||
struct dict_object *gx_subscription_id = NULL;
|
||||
struct dict_object *gx_subscription_id_type = NULL;
|
||||
struct dict_object *gx_subscription_id_data = NULL;
|
||||
struct dict_object *gx_supported_features = NULL;
|
||||
struct dict_object *gx_feature_list_id = NULL;
|
||||
struct dict_object *gx_feature_list = NULL;
|
||||
struct dict_object *gx_framed_ip_address = NULL;
|
||||
struct dict_object *gx_framed_ipv6_prefix = NULL;
|
||||
struct dict_object *gx_ip_can_type = NULL;
|
||||
struct dict_object *gx_rat_type = NULL;
|
||||
struct dict_object *gx_qos_information = NULL;
|
||||
struct dict_object *gx_qos_class_identifier = NULL;
|
||||
struct dict_object *gx_max_requested_bandwidth_ul = NULL;
|
||||
struct dict_object *gx_max_requested_bandwidth_dl = NULL;
|
||||
struct dict_object *gx_guaranteed_bitrate_ul = NULL;
|
||||
struct dict_object *gx_guaranteed_bitrate_dl = NULL;
|
||||
struct dict_object *gx_allocation_retention_priority = NULL;
|
||||
struct dict_object *gx_priority_level = NULL;
|
||||
struct dict_object *gx_pre_emption_capability = NULL;
|
||||
struct dict_object *gx_pre_emption_vulnerability = NULL;
|
||||
struct dict_object *gx_apn_aggregate_max_bitrate_ul = NULL;
|
||||
struct dict_object *gx_apn_aggregate_max_bitrate_dl = NULL;
|
||||
struct dict_object *gx_3gpp_user_location_info = NULL;
|
||||
struct dict_object *gx_called_station_id = NULL;
|
||||
struct dict_object *gx_default_eps_bearer_qos = NULL;
|
||||
|
@ -48,12 +63,27 @@ int gx_dict_init(void)
|
|||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "CC-Request-Number", &gx_cc_request_number);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Network-Request-Support", &gx_network_request_support);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Subscription-Id", &gx_subscription_id);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Subscription-Id-Type", &gx_subscription_id_type);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Subscription-Id-Data", &gx_subscription_id_data);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Supported-Features", &gx_supported_features);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Feature-List-ID", &gx_feature_list_id);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Feature-List", &gx_feature_list);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Framed-IP-Address", &gx_framed_ip_address);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Framed-IPv6-Prefix", &gx_framed_ipv6_prefix);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "IP-CAN-Type", &gx_ip_can_type);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "RAT-Type", &gx_rat_type);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "QoS-Information", &gx_qos_information);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "QoS-Class-Identifier" , &gx_qos_class_identifier);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Max-Requested-Bandwidth-UL" , &gx_max_requested_bandwidth_ul);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Max-Requested-Bandwidth-DL" , &gx_max_requested_bandwidth_dl);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Guaranteed-Bitrate-UL" , &gx_guaranteed_bitrate_ul);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Guaranteed-Bitrate-DL" , &gx_guaranteed_bitrate_dl);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Allocation-Retention-Priority" , &gx_allocation_retention_priority);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Priority-Level", &gx_priority_level);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Pre-emption-Capability", &gx_pre_emption_capability);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Pre-emption-Vulnerability", &gx_pre_emption_vulnerability);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "APN-Aggregate-Max-Bitrate-UL" , &gx_apn_aggregate_max_bitrate_ul);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "APN-Aggregate-Max-Bitrate-DL" , &gx_apn_aggregate_max_bitrate_dl);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "3GPP-User-Location-Info", &gx_3gpp_user_location_info);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Called-Station-Id", &gx_called_station_id);
|
||||
CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Default-EPS-Bearer-QoS", &gx_default_eps_bearer_qos);
|
||||
|
|
|
@ -23,12 +23,51 @@ extern struct dict_object *gx_cc_request_type;
|
|||
extern struct dict_object *gx_cc_request_number;
|
||||
extern struct dict_object *gx_network_request_support;
|
||||
extern struct dict_object *gx_subscription_id;
|
||||
#define GX_SUBSCRIPTION_ID_TYPE_END_USER_E164 0
|
||||
#define GX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI 1
|
||||
#define GX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI 2
|
||||
#define GX_SUBSCRIPTION_ID_TYPE_END_USER_NAI 3
|
||||
extern struct dict_object *gx_subscription_id_type;
|
||||
extern struct dict_object *gx_subscription_id_data;
|
||||
extern struct dict_object *gx_supported_features;
|
||||
extern struct dict_object *gx_feature_list_id;
|
||||
extern struct dict_object *gx_feature_list;
|
||||
extern struct dict_object *gx_framed_ip_address;
|
||||
extern struct dict_object *gx_framed_ipv6_prefix;
|
||||
#define GX_IP_CAN_TYPE_3GPP_GPRS 0
|
||||
#define GX_IP_CAN_TYPE_DOCSIS 1
|
||||
#define GX_IP_CAN_TYPE_xDSL 2
|
||||
#define GX_IP_CAN_TYPE_WiMAX 3
|
||||
#define GX_IP_CAN_TYPE_3GPP2 4
|
||||
#define GX_IP_CAN_TYPE_3GPP_EPS 5
|
||||
#define GX_IP_CAN_TYPE_Non_3GPP_EPS 6
|
||||
extern struct dict_object *gx_ip_can_type;
|
||||
#define GX_RAT_TYPE_WLAN 0
|
||||
#define GX_RAT_TYPE_VIRTUAL 1
|
||||
#define GX_RAT_TYPE_UTRAN 1000
|
||||
#define GX_RAT_TYPE_GERAN 1001
|
||||
#define GX_RAT_TYPE_GAN 1002
|
||||
#define GX_RAT_TYPE_HSPA_EVOLUTION 1003
|
||||
#define GX_RAT_TYPE_EUTRAN 1004
|
||||
#define GX_RAT_TYPE_EUTRAN_NB_IoT 1005
|
||||
#define GX_RAT_TYPE_CDMA2000_1X 2000
|
||||
#define GX_RAT_TYPE_HRPD 2001
|
||||
#define GX_RAT_TYPE_UMB 2002
|
||||
#define GX_RAT_TYPE_EHRPD 2003
|
||||
extern struct dict_object *gx_rat_type;
|
||||
extern struct dict_object *gx_qos_information;
|
||||
extern struct dict_object *gx_qos_class_identifier;
|
||||
extern struct dict_object *gx_max_requested_bandwidth_ul;
|
||||
extern struct dict_object *gx_max_requested_bandwidth_dl;
|
||||
extern struct dict_object *gx_guaranteed_bitrate_ul;
|
||||
extern struct dict_object *gx_guaranteed_bitrate_dl;
|
||||
extern struct dict_object *gx_allocation_retention_priority;
|
||||
extern struct dict_object *gx_priority_level;
|
||||
extern struct dict_object *gx_pre_emption_capability;
|
||||
extern struct dict_object *gx_pre_emption_vulnerability;
|
||||
extern struct dict_object *gx_apn_aggregate_max_bitrate_ul;
|
||||
extern struct dict_object *gx_apn_aggregate_max_bitrate_dl;
|
||||
#define GX_3GPP_USER_LOCATION_INFO_TYPE_TAI_AND_ECGI 130
|
||||
extern struct dict_object *gx_3gpp_user_location_info;
|
||||
extern struct dict_object *gx_called_station_id;
|
||||
extern struct dict_object *gx_default_eps_bearer_qos;
|
||||
|
|
|
@ -46,9 +46,11 @@ status_t mme_s11_build_create_session_request(pkbuf_t **pkbuf, mme_sess_t *sess)
|
|||
req->imsi.len = mme_ue->imsi_len;
|
||||
|
||||
/* Not used */
|
||||
#if 0
|
||||
req->msisdn.presence = 1;
|
||||
req->msisdn.data = mme_ue->imsi;
|
||||
req->msisdn.len = mme_ue->imsi_len;
|
||||
#endif
|
||||
|
||||
memset(&uli, 0, sizeof(gtp_uli_t));
|
||||
uli.flags.e_cgi = 1;
|
||||
|
@ -57,7 +59,7 @@ status_t mme_s11_build_create_session_request(pkbuf_t **pkbuf, mme_sess_t *sess)
|
|||
sizeof(uli.tai.plmn_id));
|
||||
uli.tai.tac = mme_ue->enb_ue->tai.tac;
|
||||
memcpy(&uli.e_cgi.plmn_id, &mme_ue->enb_ue->e_cgi.plmn_id,
|
||||
sizeof(uli.tai.plmn_id));
|
||||
sizeof(uli.e_cgi.plmn_id));
|
||||
uli.e_cgi.cell_id = mme_ue->enb_ue->e_cgi.cell_id;
|
||||
req->user_location_information.presence = 1;
|
||||
gtp_build_uli(&req->user_location_information, &uli,
|
||||
|
@ -105,12 +107,15 @@ status_t mme_s11_build_create_session_request(pkbuf_t **pkbuf, mme_sess_t *sess)
|
|||
req->maximum_apn_restriction.presence = 1;
|
||||
req->maximum_apn_restriction.u8 = GTP_APN_NO_RESTRICTION;
|
||||
|
||||
memset(&ambr, 0, sizeof(gtp_ambr_t));
|
||||
ambr.uplink = htonl(pdn->ambr.uplink);
|
||||
ambr.downlink = htonl(pdn->ambr.downlink);
|
||||
req->aggregate_maximum_bit_rate.presence = 1;
|
||||
req->aggregate_maximum_bit_rate.data = &ambr;
|
||||
req->aggregate_maximum_bit_rate.len = sizeof(ambr);
|
||||
if (pdn->ambr.uplink || pdn->ambr.downlink)
|
||||
{
|
||||
memset(&ambr, 0, sizeof(gtp_ambr_t));
|
||||
ambr.uplink = htonl(pdn->ambr.uplink);
|
||||
ambr.downlink = htonl(pdn->ambr.downlink);
|
||||
req->aggregate_maximum_bit_rate.presence = 1;
|
||||
req->aggregate_maximum_bit_rate.data = &ambr;
|
||||
req->aggregate_maximum_bit_rate.len = sizeof(ambr);
|
||||
}
|
||||
|
||||
if (bearer->ue_pco_len)
|
||||
{
|
||||
|
@ -133,6 +138,7 @@ status_t mme_s11_build_create_session_request(pkbuf_t **pkbuf, mme_sess_t *sess)
|
|||
gtp_build_bearer_qos(&req->bearer_contexts_to_be_created.bearer_level_qos,
|
||||
&bearer_qos, bearer_qos_buf, GTP_BEARER_QOS_LEN);
|
||||
|
||||
/* FIXME : where did we receive this information from MS */
|
||||
memset(&ue_timezone, 0, sizeof(ue_timezone));
|
||||
ue_timezone.timezone = 0x40;
|
||||
ue_timezone.daylight_saving_time =
|
||||
|
|
|
@ -34,7 +34,7 @@ void mme_s6a_send_air(mme_ue_t *mme_ue)
|
|||
struct sess_state *mi = NULL, *svg;
|
||||
struct session *session = NULL;
|
||||
|
||||
d_assert(mme_ue, return, "Null Param");
|
||||
d_assert(mme_ue, return, "Null param");
|
||||
|
||||
/* Clear Security Context */
|
||||
CLEAR_SECURITY_CONTEXT(mme_ue);
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
noinst_LTLIBRARIES = libpcrf.la
|
||||
|
||||
libpcrf_la_SOURCES = \
|
||||
pcrf_context.h pcrf_gx_handler.h \
|
||||
pcrf_init.c pcrf_context.c pcrf_gx_handler.c
|
||||
pcrf_context.h pcrf_fd_path.h \
|
||||
pcrf_init.c pcrf_context.c pcrf_fd_path.c
|
||||
|
||||
libpcrf_la_DEPENDENCIES = \
|
||||
$(top_srcdir)/lib/core/src/libcore.la \
|
||||
|
|
|
@ -185,8 +185,8 @@ status_t pcrf_context_setup_trace_module()
|
|||
else if (fd <= 5) fd_g_debug_lvl = FD_LOG_DEBUG;
|
||||
else fd_g_debug_lvl = FD_LOG_ANNOYING;
|
||||
|
||||
extern int _pcrf_gx_handler;
|
||||
d_trace_level(&_pcrf_gx_handler, fd);
|
||||
extern int _pcrf_fd_path;
|
||||
d_trace_level(&_pcrf_fd_path, fd);
|
||||
extern int _fd_init;
|
||||
d_trace_level(&_fd_init, fd);
|
||||
extern int _fd_logger;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#define TRACE_MODULE _pcrf_gx_handler
|
||||
#define TRACE_MODULE _pcrf_fd_path
|
||||
|
||||
#include "core_debug.h"
|
||||
|
||||
|
@ -8,12 +8,12 @@
|
|||
#include "pcrf_context.h"
|
||||
|
||||
/* handler for fallback cb */
|
||||
static struct disp_hdl *hdl_fb = NULL;
|
||||
static struct disp_hdl *hdl_gx_fb = NULL;
|
||||
/* handler for Credit-Control-Request cb */
|
||||
static struct disp_hdl *hdl_ccr = NULL;
|
||||
static struct disp_hdl *hdl_gx_ccr = NULL;
|
||||
|
||||
/* Default callback for the application. */
|
||||
static int pcrf_fb_cb(struct msg **msg, struct avp *avp,
|
||||
static int pcrf_gx_fb_cb(struct msg **msg, struct avp *avp,
|
||||
struct session *sess, void *opaque, enum disp_action *act)
|
||||
{
|
||||
/* This CB should never be called */
|
||||
|
@ -23,7 +23,7 @@ static int pcrf_fb_cb(struct msg **msg, struct avp *avp,
|
|||
}
|
||||
|
||||
/* Callback for incoming Credit-Control-Request messages */
|
||||
static int pcrf_ccr_cb( struct msg **msg, struct avp *avp,
|
||||
static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp,
|
||||
struct session *sess, void *opaque, enum disp_action *act)
|
||||
{
|
||||
struct msg *ans, *qry;
|
||||
|
@ -89,7 +89,7 @@ out:
|
|||
return 0;
|
||||
}
|
||||
|
||||
int pcrf_gx_init(void)
|
||||
int pcrf_fd_init(void)
|
||||
{
|
||||
struct disp_when data;
|
||||
|
||||
|
@ -102,13 +102,13 @@ int pcrf_gx_init(void)
|
|||
data.app = gx_application;
|
||||
|
||||
/* fallback CB if command != unexpected message received */
|
||||
CHECK_FCT( fd_disp_register(pcrf_fb_cb, DISP_HOW_APPID, &data, NULL,
|
||||
&hdl_fb) );
|
||||
CHECK_FCT( fd_disp_register(pcrf_gx_fb_cb, DISP_HOW_APPID, &data, NULL,
|
||||
&hdl_gx_fb) );
|
||||
|
||||
/* specific handler for Credit-Control-Request */
|
||||
data.command = gx_cmd_ccr;
|
||||
CHECK_FCT( fd_disp_register(pcrf_ccr_cb, DISP_HOW_CC, &data, NULL,
|
||||
&hdl_ccr) );
|
||||
CHECK_FCT( fd_disp_register(pcrf_gx_ccr_cb, DISP_HOW_CC, &data, NULL,
|
||||
&hdl_gx_ccr) );
|
||||
|
||||
/* Advertise the support for the application in the peer */
|
||||
CHECK_FCT( fd_disp_app_support(gx_application, fd_vendor, 1, 0) );
|
||||
|
@ -116,13 +116,13 @@ int pcrf_gx_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void pcrf_gx_final(void)
|
||||
void pcrf_fd_final(void)
|
||||
{
|
||||
if (hdl_fb) {
|
||||
(void) fd_disp_unregister(&hdl_fb, NULL);
|
||||
if (hdl_gx_fb) {
|
||||
(void) fd_disp_unregister(&hdl_gx_fb, NULL);
|
||||
}
|
||||
if (hdl_ccr) {
|
||||
(void) fd_disp_unregister(&hdl_ccr, NULL);
|
||||
if (hdl_gx_ccr) {
|
||||
(void) fd_disp_unregister(&hdl_gx_ccr, NULL);
|
||||
}
|
||||
|
||||
fd_final();
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef __PCRF_FD_PATH_H__
|
||||
#define __PCRF_FD_PATH_H__
|
||||
|
||||
#include "core_errno.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
CORE_DECLARE(int) pcrf_fd_init(void);
|
||||
CORE_DECLARE(void) pcrf_fd_final(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __PCRF_FD_PATH_H__ */
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef __PCRF_GX_HANDLER_H__
|
||||
#define __PCRF_GX_HANDLER_H__
|
||||
|
||||
#include "core_errno.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
CORE_DECLARE(int) pcrf_gx_init(void);
|
||||
CORE_DECLARE(void) pcrf_gx_final(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __PCRF_GX_HANDLER_H__ */
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
#define TRACE_MODULE _pcrf_init
|
||||
|
||||
#include "pcrf_context.h"
|
||||
#include "pcrf_gx_handler.h"
|
||||
#include "pcrf_fd_path.h"
|
||||
|
||||
static int initialized = 0;
|
||||
|
||||
|
@ -22,7 +22,7 @@ status_t pcrf_initialize(void)
|
|||
rv = pcrf_db_init();
|
||||
if (rv != CORE_OK) return rv;
|
||||
|
||||
ret = pcrf_gx_init();
|
||||
ret = pcrf_fd_init();
|
||||
if (ret != CORE_OK) return CORE_ERROR;
|
||||
|
||||
initialized = 1;
|
||||
|
@ -34,7 +34,7 @@ void pcrf_terminate(void)
|
|||
{
|
||||
if (!initialized) return;
|
||||
|
||||
pcrf_gx_final();
|
||||
pcrf_fd_final();
|
||||
|
||||
pcrf_db_final();
|
||||
pcrf_context_final();
|
||||
|
|
|
@ -4,9 +4,11 @@ noinst_LTLIBRARIES = libpgw.la
|
|||
|
||||
libpgw_la_SOURCES = \
|
||||
pgw_event.h pgw_context.h pgw_sm.h \
|
||||
pgw_gtp_path.h pgw_s5c_handler.h pgw_gx_handler.h \
|
||||
pgw_gtp_path.h pgw_s5c_handler.h \
|
||||
pgw_fd_path.h pgw_gx_handler.h \
|
||||
pgw_init.c pgw_event.c pgw_context.c pgw_sm.c \
|
||||
pgw_gtp_path.c pgw_s5c_handler.c pgw_gx_handler.c
|
||||
pgw_gtp_path.c pgw_s5c_handler.c \
|
||||
pgw_fd_path.c pgw_gx_handler.c
|
||||
|
||||
libpgw_la_DEPENDENCIES = \
|
||||
$(top_srcdir)/lib/core/src/libcore.la \
|
||||
|
|
|
@ -429,8 +429,8 @@ status_t pgw_context_setup_trace_module()
|
|||
else if (fd <= 5) fd_g_debug_lvl = FD_LOG_DEBUG;
|
||||
else fd_g_debug_lvl = FD_LOG_ANNOYING;
|
||||
|
||||
extern int _pgw_gx_handler;
|
||||
d_trace_level(&_pgw_gx_handler, fd);
|
||||
extern int _pgw_fd_path;
|
||||
d_trace_level(&_pgw_fd_path, fd);
|
||||
extern int _fd_init;
|
||||
d_trace_level(&_fd_init, fd);
|
||||
extern int _fd_logger;
|
||||
|
@ -483,7 +483,7 @@ pgw_bearer_t *pgw_sess_add(c_int8_t *apn, c_uint8_t id)
|
|||
list_init(&sess->bearer_list);
|
||||
list_append(&self.sess_list, sess);
|
||||
|
||||
strcpy(sess->apn, apn);
|
||||
strcpy(sess->pdn.apn, apn);
|
||||
|
||||
bearer = pgw_bearer_add(sess, id);
|
||||
d_assert(bearer, pgw_sess_remove(sess); return NULL,
|
||||
|
@ -545,7 +545,7 @@ pgw_sess_t* pgw_sess_find_by_apn(c_int8_t *apn)
|
|||
sess = pgw_sess_first();
|
||||
while (sess)
|
||||
{
|
||||
if (strcmp(sess->apn, apn) == 0)
|
||||
if (strcmp(sess->pdn.apn, apn) == 0)
|
||||
break;
|
||||
|
||||
sess = pgw_sess_next(sess);
|
||||
|
@ -687,9 +687,9 @@ pgw_bearer_t* pgw_bearer_find_by_packet(pkbuf_t *pkt)
|
|||
{
|
||||
d_trace(50, "Dst(%s) in Pkt : PAA(%s) in PDN\n",
|
||||
INET_NTOP(&iph->ip_dst.s_addr,buf1),
|
||||
INET_NTOP(&sess->paa.ipv4_addr, buf2));
|
||||
INET_NTOP(&sess->pdn.paa.ipv4_addr, buf2));
|
||||
|
||||
if (iph->ip_dst.s_addr == sess->paa.ipv4_addr)
|
||||
if (iph->ip_dst.s_addr == sess->pdn.paa.ipv4_addr)
|
||||
{
|
||||
/* Found */
|
||||
bearer = pgw_default_bearer_in_sess(sess);
|
||||
|
|
|
@ -72,10 +72,19 @@ typedef struct _pgw_sess_t {
|
|||
/* Last Received GTP Messasge */
|
||||
gtp_message_t last_gtp_message;
|
||||
|
||||
c_int8_t apn[MAX_APN_LEN];
|
||||
paa_t paa;
|
||||
/* IMSI */
|
||||
c_uint8_t imsi[MAX_IMSI_LEN];
|
||||
int imsi_len;
|
||||
c_int8_t imsi_bcd[MAX_IMSI_BCD_LEN+1];
|
||||
|
||||
/* APN Configuration */
|
||||
pdn_t pdn;
|
||||
pgw_ip_pool_t* ip_pool;
|
||||
|
||||
/* User-Lication-Info */
|
||||
tai_t tai;
|
||||
e_cgi_t e_cgi;
|
||||
|
||||
list_t bearer_list;
|
||||
} pgw_sess_t;
|
||||
|
||||
|
|
|
@ -0,0 +1,493 @@
|
|||
#define TRACE_MODULE _pgw_fd_path
|
||||
|
||||
#include "core_debug.h"
|
||||
#include "core_pool.h"
|
||||
|
||||
#include "fd_lib.h"
|
||||
#include "gx_lib.h"
|
||||
|
||||
#include "pgw_event.h"
|
||||
#include "pgw_fd_path.h"
|
||||
|
||||
#define MAX_NUM_SESSION_STATE 32
|
||||
|
||||
static struct session_handler *pgw_gx_reg = NULL;
|
||||
|
||||
struct sess_state {
|
||||
gtp_xact_t *xact;
|
||||
pgw_sess_t *sess;
|
||||
struct timespec ts; /* Time of sending the message */
|
||||
};
|
||||
|
||||
pool_declare(pgw_gx_sess_pool, struct sess_state, MAX_NUM_SESSION_STATE);
|
||||
|
||||
static void pgw_gx_cca_cb(void *data, struct msg **msg);
|
||||
|
||||
void pgw_gx_send_ccr(
|
||||
gtp_xact_t *xact, pgw_sess_t *sess, c_uint32_t cc_request_type)
|
||||
{
|
||||
struct msg *req = NULL;
|
||||
struct avp *avp;
|
||||
struct avp *avpch1, *avpch2;
|
||||
union avp_value val;
|
||||
struct sess_state *mi = NULL, *svg;
|
||||
struct session *session = NULL;
|
||||
|
||||
d_assert(sess, return, "Null param");
|
||||
d_assert(sess->ip_pool, return, "Null param");
|
||||
|
||||
/* Create the random value to store with the session */
|
||||
pool_alloc_node(&pgw_gx_sess_pool, &mi);
|
||||
d_assert(mi, return, "malloc failed: %s", strerror(errno));
|
||||
|
||||
mi->xact = xact;
|
||||
mi->sess = sess;
|
||||
|
||||
/* Create the request */
|
||||
CHECK_FCT_DO( fd_msg_new(gx_cmd_ccr, MSGFL_ALLOC_ETEID, &req), goto out );
|
||||
|
||||
/* Create a new session */
|
||||
#define GX_APP_SID_OPT "app_gx"
|
||||
CHECK_FCT_DO( fd_msg_new_session(req, (os0_t)GX_APP_SID_OPT,
|
||||
CONSTSTRLEN(GX_APP_SID_OPT)), goto out );
|
||||
CHECK_FCT_DO( fd_msg_sess_get(fd_g_config->cnf_dict, req, &session, NULL),
|
||||
goto out );
|
||||
|
||||
/* Set Origin-Host & Origin-Realm */
|
||||
CHECK_FCT_DO( fd_msg_add_origin(req, 0), goto out );
|
||||
|
||||
/* Set the Destination-Realm AVP */
|
||||
CHECK_FCT_DO( fd_msg_avp_new(fd_destination_realm, 0, &avp), goto out );
|
||||
val.os.data = (unsigned char *)(fd_g_config->cnf_diamrlm);
|
||||
val.os.len = strlen(fd_g_config->cnf_diamrlm);
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
/* Set the Auth-Application-Id AVP */
|
||||
CHECK_FCT_DO( fd_msg_avp_new(fd_auth_application_id, 0, &avp), goto out );
|
||||
val.i32 = GX_APPLICATION_ID;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
/* Set CC-Request-Type, CC-Request-Number */
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_cc_request_type, 0, &avp), goto out );
|
||||
val.i32 = cc_request_type;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_cc_request_number, 0, &avp), goto out );
|
||||
val.i32 = 0;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
/* Set Subscription-Id */
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_subscription_id, 0, &avp),
|
||||
goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_subscription_id_type, 0, &avpch1),
|
||||
goto out );
|
||||
val.i32 = GX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue (avpch1, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1), goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_subscription_id_data, 0, &avpch1),
|
||||
goto out );
|
||||
val.os.data = (c_uint8_t *)sess->imsi_bcd;
|
||||
val.os.len = strlen(sess->imsi_bcd);
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue (avpch1, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1), goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
/* Set Supported-Features */
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_supported_features, 0, &avp),
|
||||
goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_feature_list_id, 0, &avpch1),
|
||||
goto out );
|
||||
val.i32 = 1;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue (avpch1, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1), goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_feature_list, 0, &avpch1),
|
||||
goto out );
|
||||
val.u32 = 0x0000000b;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue (avpch1, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1), goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
/* Set Network-Request-Support */
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_network_request_support, 0, &avp),
|
||||
goto out );
|
||||
val.i32 = 1;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
/* Set Framed-IP-Address */
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_framed_ip_address, 0, &avp),
|
||||
goto out );
|
||||
val.os.data = (c_uint8_t*)&sess->ip_pool->ue_addr;
|
||||
val.os.len = sizeof(sess->ip_pool->ue_addr);
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
/* Set IP-Can-Type */
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_ip_can_type, 0, &avp),
|
||||
goto out );
|
||||
val.i32 = GX_IP_CAN_TYPE_3GPP_EPS;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
/* Set RAT-Type */
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_rat_type, 0, &avp),
|
||||
goto out );
|
||||
val.i32 = GX_RAT_TYPE_EUTRAN;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
/* Set QoS-Information */
|
||||
if (sess->pdn.ambr.downlink || sess->pdn.ambr.uplink)
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_qos_information, 0, &avp),
|
||||
goto out );
|
||||
|
||||
if (sess->pdn.ambr.uplink)
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_apn_aggregate_max_bitrate_ul, 0,
|
||||
&avpch1), goto out );
|
||||
val.u32 = sess->pdn.ambr.uplink;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue (avpch1, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1),
|
||||
goto out );
|
||||
}
|
||||
|
||||
if (sess->pdn.ambr.downlink)
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_apn_aggregate_max_bitrate_dl, 0,
|
||||
&avpch1), goto out );
|
||||
val.u32 = sess->pdn.ambr.downlink;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue (avpch1, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1),
|
||||
goto out );
|
||||
}
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
}
|
||||
|
||||
/* Set Default-EPS-Bearer-QoS */
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_default_eps_bearer_qos, 0, &avp),
|
||||
goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_qos_class_identifier, 0, &avpch1),
|
||||
goto out );
|
||||
val.u32 = sess->pdn.qos.qci;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue (avpch1, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1),
|
||||
goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_allocation_retention_priority, 0, &avpch1),
|
||||
goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_priority_level, 0, &avpch2), goto out );
|
||||
val.u32 = sess->pdn.qos.arp.priority_level;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue (avpch2, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2),
|
||||
goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_pre_emption_capability, 0, &avpch2),
|
||||
goto out );
|
||||
val.u32 = sess->pdn.qos.arp.pre_emption_capability;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue (avpch2, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2),
|
||||
goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_pre_emption_vulnerability, 0, &avpch2),
|
||||
goto out );
|
||||
val.u32 = sess->pdn.qos.arp.pre_emption_vulnerability;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue (avpch2, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2),
|
||||
goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1),
|
||||
goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
/* Set 3GPP-User-Location-Info */
|
||||
{
|
||||
struct gx_uli_t {
|
||||
c_uint8_t type;
|
||||
tai_t tai;
|
||||
e_cgi_t e_cgi;
|
||||
} gx_uli;
|
||||
|
||||
memset(&gx_uli, 0, sizeof(gx_uli));
|
||||
gx_uli.type = GX_3GPP_USER_LOCATION_INFO_TYPE_TAI_AND_ECGI;
|
||||
memcpy(&gx_uli.tai.plmn_id, &sess->tai.plmn_id,
|
||||
sizeof(sess->tai.plmn_id));
|
||||
gx_uli.tai.tac = htons(sess->tai.tac);
|
||||
memcpy(&gx_uli.e_cgi.plmn_id, &sess->e_cgi.plmn_id,
|
||||
sizeof(sess->e_cgi.plmn_id));
|
||||
gx_uli.e_cgi.cell_id = htonl(sess->e_cgi.cell_id);
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_3gpp_user_location_info, 0, &avp),
|
||||
goto out );
|
||||
val.os.data = (c_uint8_t*)&gx_uli;
|
||||
val.os.len = sizeof(gx_uli);
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
}
|
||||
|
||||
/* Set 3GPP-MS-Timezone */
|
||||
{
|
||||
gtp_ue_timezone_t ue_timezone;
|
||||
memset(&ue_timezone, 0, sizeof(ue_timezone));
|
||||
ue_timezone.timezone = 0x40;
|
||||
ue_timezone.daylight_saving_time =
|
||||
GTP_UE_TIME_ZONE_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME;
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_3gpp_ms_timezone, 0, &avp),
|
||||
goto out );
|
||||
val.os.data = (c_uint8_t*)&ue_timezone;
|
||||
val.os.len = sizeof(ue_timezone);
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
}
|
||||
|
||||
/* Set Called-Station-Id */
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_called_station_id, 0, &avp),
|
||||
goto out );
|
||||
val.os.data = (c_uint8_t*)sess->pdn.apn;
|
||||
val.os.len = strlen(sess->pdn.apn);
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &mi->ts), goto out );
|
||||
|
||||
/* Keep a pointer to the session data for debug purpose,
|
||||
* in real life we would not need it */
|
||||
svg = mi;
|
||||
|
||||
/* Store this value in the session */
|
||||
CHECK_FCT_DO( fd_sess_state_store(pgw_gx_reg, session, &mi), goto out );
|
||||
|
||||
/* Send the request */
|
||||
CHECK_FCT_DO( fd_msg_send(&req, pgw_gx_cca_cb, svg), goto out );
|
||||
|
||||
/* Increment the counter */
|
||||
CHECK_POSIX_DO( pthread_mutex_lock(&fd_logger_self()->stats_lock), );
|
||||
fd_logger_self()->stats.nb_sent++;
|
||||
CHECK_POSIX_DO( pthread_mutex_unlock(&fd_logger_self()->stats_lock), );
|
||||
|
||||
d_trace(3, "[Gx] Credit-Control-Request : PGW[%d] --> PCRF\n",
|
||||
sess->pgw_s5c_teid);
|
||||
|
||||
out:
|
||||
pool_free_node(&pgw_gx_sess_pool, mi);
|
||||
return;
|
||||
}
|
||||
|
||||
static void pgw_gx_cca_cb(void *data, struct msg **msg)
|
||||
{
|
||||
struct sess_state *mi = NULL;
|
||||
struct timespec ts;
|
||||
struct session *session;
|
||||
struct avp *avp, *avpch1;
|
||||
#if 0
|
||||
struct avp *avp_e_utran_vector, *avp_xres, *avp_kasme, *avp_rand, *avp_autn;
|
||||
#endif
|
||||
struct avp_hdr *hdr;
|
||||
unsigned long dur;
|
||||
int error = 0;
|
||||
c_uint32_t result_code = 0;
|
||||
c_uint32_t cc_request_type = 0;
|
||||
int new;
|
||||
|
||||
event_t e;
|
||||
gtp_xact_t *xact = NULL;
|
||||
pgw_sess_t *sess = NULL;
|
||||
|
||||
CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return );
|
||||
|
||||
/* Search the session, retrieve its data */
|
||||
CHECK_FCT_DO( fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new),
|
||||
return );
|
||||
d_assert(new == 0, return, );
|
||||
|
||||
CHECK_FCT_DO( fd_sess_state_retrieve(pgw_gx_reg, session, &mi), return );
|
||||
d_assert(mi && (void *)mi == data, return, );
|
||||
|
||||
xact = mi->xact;
|
||||
d_assert(xact, return, );
|
||||
sess = mi->sess;
|
||||
d_assert(sess, return, );
|
||||
|
||||
d_trace(3, "[Gx] Credit-Control-Answer : PGW[%d] <-- PCRF\n",
|
||||
sess->pgw_s5c_teid);
|
||||
|
||||
/* Value of Result Code */
|
||||
CHECK_FCT_DO( fd_msg_search_avp(*msg, fd_result_code, &avp), return );
|
||||
if (avp)
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_avp_hdr(avp, &hdr), return);
|
||||
result_code = hdr->avp_value->i32;
|
||||
d_trace(3, "Result Code: %d\n", hdr->avp_value->i32);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_search_avp(*msg,
|
||||
fd_experimental_result, &avp), return );
|
||||
if (avp)
|
||||
{
|
||||
CHECK_FCT_DO( fd_avp_search_avp(avp,
|
||||
fd_experimental_result_code, &avpch1), return );
|
||||
if (avpch1)
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_avp_hdr(avpch1, &hdr), return);
|
||||
result_code = hdr->avp_value->i32;
|
||||
d_trace(3, "Experimental Result Code: %d\n", result_code);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
d_error("no Result-Code");
|
||||
error++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Value of Origin-Host */
|
||||
CHECK_FCT_DO( fd_msg_search_avp(*msg, fd_origin_host, &avp), return );
|
||||
if (avp)
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_avp_hdr(avp, &hdr), return );
|
||||
d_trace(3, "From '%.*s' ",
|
||||
(int)hdr->avp_value->os.len, hdr->avp_value->os.data);
|
||||
}
|
||||
else
|
||||
{
|
||||
d_error("no_Origin-Host ");
|
||||
error++;
|
||||
}
|
||||
|
||||
/* Value of Origin-Realm */
|
||||
CHECK_FCT_DO( fd_msg_search_avp(*msg, fd_origin_realm, &avp), return );
|
||||
if (avp)
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_avp_hdr(avp, &hdr), return );
|
||||
d_trace(3, "('%.*s') ",
|
||||
(int)hdr->avp_value->os.len, hdr->avp_value->os.data);
|
||||
}
|
||||
else
|
||||
{
|
||||
d_error("no_Origin-Realm ");
|
||||
error++;
|
||||
}
|
||||
|
||||
if (result_code != ER_DIAMETER_SUCCESS)
|
||||
{
|
||||
d_warn("ERROR DIAMETER Result Code(%d)", result_code);
|
||||
error++;
|
||||
goto out;
|
||||
}
|
||||
|
||||
CHECK_FCT_DO(
|
||||
fd_msg_search_avp(*msg, gx_cc_request_type, &avp), return );
|
||||
if (avp)
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_avp_hdr(avp, &hdr), return );
|
||||
cc_request_type = hdr->avp_value->i32;
|
||||
}
|
||||
else
|
||||
error++;
|
||||
|
||||
out:
|
||||
event_set(&e, PGW_EVT_S5C_SESSION_FROM_GX);
|
||||
event_set_param1(&e, (c_uintptr_t)xact->index);
|
||||
event_set_param2(&e, (c_uintptr_t)sess->index);
|
||||
event_set_param3(&e, (c_uintptr_t)GX_CMD_CREDIT_CONTROL);
|
||||
event_set_param4(&e, (c_uintptr_t)cc_request_type);
|
||||
event_set_param5(&e, (c_uintptr_t)result_code);
|
||||
pgw_event_send(&e);
|
||||
|
||||
/* Free the message */
|
||||
CHECK_POSIX_DO( pthread_mutex_lock(&fd_logger_self()->stats_lock), );
|
||||
dur = ((ts.tv_sec - mi->ts.tv_sec) * 1000000) +
|
||||
((ts.tv_nsec - mi->ts.tv_nsec) / 1000);
|
||||
if (fd_logger_self()->stats.nb_recv)
|
||||
{
|
||||
/* Ponderate in the avg */
|
||||
fd_logger_self()->stats.avg = (fd_logger_self()->stats.avg *
|
||||
fd_logger_self()->stats.nb_recv + dur) /
|
||||
(fd_logger_self()->stats.nb_recv + 1);
|
||||
/* Min, max */
|
||||
if (dur < fd_logger_self()->stats.shortest)
|
||||
fd_logger_self()->stats.shortest = dur;
|
||||
if (dur > fd_logger_self()->stats.longest)
|
||||
fd_logger_self()->stats.longest = dur;
|
||||
}
|
||||
else
|
||||
{
|
||||
fd_logger_self()->stats.shortest = dur;
|
||||
fd_logger_self()->stats.longest = dur;
|
||||
fd_logger_self()->stats.avg = dur;
|
||||
}
|
||||
if (error)
|
||||
fd_logger_self()->stats.nb_errs++;
|
||||
else
|
||||
fd_logger_self()->stats.nb_recv++;
|
||||
|
||||
CHECK_POSIX_DO( pthread_mutex_unlock(&fd_logger_self()->stats_lock), );
|
||||
|
||||
/* Display how long it took */
|
||||
if (ts.tv_nsec > mi->ts.tv_nsec)
|
||||
d_trace(3, "in %d.%06ld sec\n",
|
||||
(int)(ts.tv_sec - mi->ts.tv_sec),
|
||||
(long)(ts.tv_nsec - mi->ts.tv_nsec) / 1000);
|
||||
else
|
||||
d_trace(3, "in %d.%06ld sec\n",
|
||||
(int)(ts.tv_sec + 1 - mi->ts.tv_sec),
|
||||
(long)(1000000000 + ts.tv_nsec - mi->ts.tv_nsec) / 1000);
|
||||
|
||||
CHECK_FCT_DO( fd_msg_free(*msg), return );
|
||||
*msg = NULL;
|
||||
|
||||
pool_free_node(&pgw_gx_sess_pool, mi);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int pgw_fd_init(void)
|
||||
{
|
||||
pool_init(&pgw_gx_sess_pool, MAX_NUM_SESSION_STATE);
|
||||
|
||||
CHECK_FCT( fd_init(FD_MODE_CLIENT, pgw_self()->fd_conf_path) );
|
||||
|
||||
/* Install objects definitions for this application */
|
||||
CHECK_FCT( gx_dict_init() );
|
||||
|
||||
CHECK_FCT( fd_sess_handler_create(&pgw_gx_reg, (void *)free, NULL, NULL) );
|
||||
|
||||
/* Advertise the support for the application in the peer */
|
||||
CHECK_FCT( fd_disp_app_support(gx_application, fd_vendor, 1, 0) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pgw_fd_final(void)
|
||||
{
|
||||
CHECK_FCT_DO( fd_sess_handler_destroy(&pgw_gx_reg, NULL), );
|
||||
|
||||
fd_final();
|
||||
|
||||
if (pool_size(&pgw_gx_sess_pool) != pool_avail(&pgw_gx_sess_pool))
|
||||
d_error("%d not freed in pgw_gx_sess_pool[%d] of S6A-SM",
|
||||
pool_size(&pgw_gx_sess_pool) - pool_avail(&pgw_gx_sess_pool),
|
||||
pool_size(&pgw_gx_sess_pool));
|
||||
|
||||
d_trace(3, "%d not freed in pgw_gx_sess_pool[%d] of S6A-SM\n",
|
||||
pool_size(&pgw_gx_sess_pool) - pool_avail(&pgw_gx_sess_pool),
|
||||
pool_size(&pgw_gx_sess_pool));
|
||||
|
||||
pool_final(&pgw_gx_sess_pool);
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef __PGW_FD_PATH_H__
|
||||
#define __PGW_FD_PATH_H__
|
||||
|
||||
#include "core_errno.h"
|
||||
|
||||
#include "pgw_context.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
CORE_DECLARE(int) pgw_fd_init(void);
|
||||
CORE_DECLARE(void) pgw_fd_final(void);
|
||||
|
||||
CORE_DECLARE(void) pgw_gx_send_ccr(
|
||||
gtp_xact_t *xact, pgw_sess_t *sess, c_uint32_t cc_request_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __PGW_FD_PATH_H__ */
|
||||
|
|
@ -1,311 +1,9 @@
|
|||
#define TRACE_MODULE _pgw_gx_handler
|
||||
|
||||
#include "core_debug.h"
|
||||
#include "core_pool.h"
|
||||
|
||||
#include "fd_lib.h"
|
||||
#include "gx_lib.h"
|
||||
#include "pgw_context.h"
|
||||
|
||||
#include "pgw_event.h"
|
||||
#include "pgw_gx_handler.h"
|
||||
|
||||
#define MAX_NUM_SESSION_STATE 32
|
||||
|
||||
static struct session_handler *pgw_gx_reg = NULL;
|
||||
|
||||
struct sess_state {
|
||||
gtp_xact_t *xact;
|
||||
pgw_sess_t *sess;
|
||||
struct timespec ts; /* Time of sending the message */
|
||||
};
|
||||
|
||||
pool_declare(pgw_gx_sess_pool, struct sess_state, MAX_NUM_SESSION_STATE);
|
||||
|
||||
static void pgw_gx_cca_cb(void *data, struct msg **msg);
|
||||
|
||||
void pgw_gx_send_ccr(
|
||||
gtp_xact_t *xact, pgw_sess_t *sess, c_uint32_t cc_request_type)
|
||||
void pgw_gx_handle_cca()
|
||||
{
|
||||
struct msg *req = NULL;
|
||||
struct avp *avp;
|
||||
#if 0
|
||||
struct avp *avpch;
|
||||
#endif
|
||||
union avp_value val;
|
||||
struct sess_state *mi = NULL, *svg;
|
||||
struct session *session = NULL;
|
||||
|
||||
d_assert(sess, return, "Null Param");
|
||||
|
||||
/* Create the random value to store with the session */
|
||||
pool_alloc_node(&pgw_gx_sess_pool, &mi);
|
||||
d_assert(mi, return, "malloc failed: %s", strerror(errno));
|
||||
|
||||
mi->xact = xact;
|
||||
mi->sess = sess;
|
||||
|
||||
/* Create the request */
|
||||
CHECK_FCT_DO( fd_msg_new(gx_cmd_ccr, MSGFL_ALLOC_ETEID, &req), goto out );
|
||||
|
||||
/* Create a new session */
|
||||
#define GX_APP_SID_OPT "app_gx"
|
||||
CHECK_FCT_DO( fd_msg_new_session(req, (os0_t)GX_APP_SID_OPT,
|
||||
CONSTSTRLEN(GX_APP_SID_OPT)), goto out );
|
||||
CHECK_FCT_DO( fd_msg_sess_get(fd_g_config->cnf_dict, req, &session, NULL),
|
||||
goto out );
|
||||
|
||||
/* Set Origin-Host & Origin-Realm */
|
||||
CHECK_FCT_DO( fd_msg_add_origin(req, 0), goto out );
|
||||
|
||||
/* Set the Destination-Realm AVP */
|
||||
CHECK_FCT_DO( fd_msg_avp_new(fd_destination_realm, 0, &avp), goto out );
|
||||
val.os.data = (unsigned char *)(fd_g_config->cnf_diamrlm);
|
||||
val.os.len = strlen(fd_g_config->cnf_diamrlm);
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
/* Set the Auth-Application-Id AVP */
|
||||
CHECK_FCT_DO( fd_msg_avp_new(fd_auth_application_id, 0, &avp), goto out );
|
||||
val.i32 = GX_APPLICATION_ID;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
/* Set CC-Request-Type, CC-Request-Number */
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_cc_request_type, 0, &avp), goto out );
|
||||
val.i32 = cc_request_type;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
CHECK_FCT_DO( fd_msg_avp_new(gx_cc_request_number, 0, &avp), goto out );
|
||||
val.i32 = 0;
|
||||
CHECK_FCT_DO( fd_msg_avp_setvalue(avp, &val), goto out );
|
||||
CHECK_FCT_DO( fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp), goto out );
|
||||
|
||||
CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &mi->ts), goto out );
|
||||
|
||||
/* Keep a pointer to the session data for debug purpose,
|
||||
* in real life we would not need it */
|
||||
svg = mi;
|
||||
|
||||
/* Store this value in the session */
|
||||
CHECK_FCT_DO( fd_sess_state_store(pgw_gx_reg, session, &mi), goto out );
|
||||
|
||||
/* Send the request */
|
||||
CHECK_FCT_DO( fd_msg_send(&req, pgw_gx_cca_cb, svg), goto out );
|
||||
|
||||
/* Increment the counter */
|
||||
CHECK_POSIX_DO( pthread_mutex_lock(&fd_logger_self()->stats_lock), );
|
||||
fd_logger_self()->stats.nb_sent++;
|
||||
CHECK_POSIX_DO( pthread_mutex_unlock(&fd_logger_self()->stats_lock), );
|
||||
|
||||
d_trace(3, "[Gx] Credit-Control-Request : PGW[%d] --> PCRF\n",
|
||||
sess->pgw_s5c_teid);
|
||||
|
||||
out:
|
||||
pool_free_node(&pgw_gx_sess_pool, mi);
|
||||
return;
|
||||
}
|
||||
|
||||
static void pgw_gx_cca_cb(void *data, struct msg **msg)
|
||||
{
|
||||
struct sess_state *mi = NULL;
|
||||
struct timespec ts;
|
||||
struct session *session;
|
||||
struct avp *avp, *avpch;
|
||||
#if 0
|
||||
struct avp *avp_e_utran_vector, *avp_xres, *avp_kasme, *avp_rand, *avp_autn;
|
||||
#endif
|
||||
struct avp_hdr *hdr;
|
||||
unsigned long dur;
|
||||
int error = 0;
|
||||
c_uint32_t result_code = 0;
|
||||
c_uint32_t cc_request_type = 0;
|
||||
int new;
|
||||
|
||||
event_t e;
|
||||
gtp_xact_t *xact = NULL;
|
||||
pgw_sess_t *sess = NULL;
|
||||
|
||||
CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return );
|
||||
|
||||
/* Search the session, retrieve its data */
|
||||
CHECK_FCT_DO( fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new),
|
||||
return );
|
||||
d_assert(new == 0, return, );
|
||||
|
||||
CHECK_FCT_DO( fd_sess_state_retrieve(pgw_gx_reg, session, &mi), return );
|
||||
d_assert(mi && (void *)mi == data, return, );
|
||||
|
||||
xact = mi->xact;
|
||||
d_assert(xact, return, );
|
||||
sess = mi->sess;
|
||||
d_assert(sess, return, );
|
||||
|
||||
d_trace(3, "[Gx] Credit-Control-Answer : PGW[%d] <-- PCRF\n",
|
||||
sess->pgw_s5c_teid);
|
||||
|
||||
/* Value of Result Code */
|
||||
CHECK_FCT_DO( fd_msg_search_avp(*msg, fd_result_code, &avp), return );
|
||||
if (avp)
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_avp_hdr(avp, &hdr), return);
|
||||
result_code = hdr->avp_value->i32;
|
||||
d_trace(3, "Result Code: %d\n", hdr->avp_value->i32);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_search_avp(*msg,
|
||||
fd_experimental_result, &avp), return );
|
||||
if (avp)
|
||||
{
|
||||
CHECK_FCT_DO( fd_avp_search_avp(avp,
|
||||
fd_experimental_result_code, &avpch), return );
|
||||
if (avpch)
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_avp_hdr(avpch, &hdr), return);
|
||||
result_code = hdr->avp_value->i32;
|
||||
d_trace(3, "Experimental Result Code: %d\n", result_code);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
d_error("no Result-Code");
|
||||
error++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Value of Origin-Host */
|
||||
CHECK_FCT_DO( fd_msg_search_avp(*msg, fd_origin_host, &avp), return );
|
||||
if (avp)
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_avp_hdr(avp, &hdr), return );
|
||||
d_trace(3, "From '%.*s' ",
|
||||
(int)hdr->avp_value->os.len, hdr->avp_value->os.data);
|
||||
}
|
||||
else
|
||||
{
|
||||
d_error("no_Origin-Host ");
|
||||
error++;
|
||||
}
|
||||
|
||||
/* Value of Origin-Realm */
|
||||
CHECK_FCT_DO( fd_msg_search_avp(*msg, fd_origin_realm, &avp), return );
|
||||
if (avp)
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_avp_hdr(avp, &hdr), return );
|
||||
d_trace(3, "('%.*s') ",
|
||||
(int)hdr->avp_value->os.len, hdr->avp_value->os.data);
|
||||
}
|
||||
else
|
||||
{
|
||||
d_error("no_Origin-Realm ");
|
||||
error++;
|
||||
}
|
||||
|
||||
if (result_code != ER_DIAMETER_SUCCESS)
|
||||
{
|
||||
d_warn("ERROR DIAMETER Result Code(%d)", result_code);
|
||||
error++;
|
||||
goto out;
|
||||
}
|
||||
|
||||
CHECK_FCT_DO(
|
||||
fd_msg_search_avp(*msg, gx_cc_request_type, &avp), return );
|
||||
if (avp)
|
||||
{
|
||||
CHECK_FCT_DO( fd_msg_avp_hdr(avp, &hdr), return );
|
||||
cc_request_type = hdr->avp_value->i32;
|
||||
}
|
||||
else
|
||||
error++;
|
||||
|
||||
out:
|
||||
event_set(&e, PGW_EVT_S5C_SESSION_FROM_GX);
|
||||
event_set_param1(&e, (c_uintptr_t)xact->index);
|
||||
event_set_param2(&e, (c_uintptr_t)sess->index);
|
||||
event_set_param3(&e, (c_uintptr_t)GX_CMD_CREDIT_CONTROL);
|
||||
event_set_param4(&e, (c_uintptr_t)cc_request_type);
|
||||
event_set_param5(&e, (c_uintptr_t)result_code);
|
||||
pgw_event_send(&e);
|
||||
|
||||
/* Free the message */
|
||||
CHECK_POSIX_DO( pthread_mutex_lock(&fd_logger_self()->stats_lock), );
|
||||
dur = ((ts.tv_sec - mi->ts.tv_sec) * 1000000) +
|
||||
((ts.tv_nsec - mi->ts.tv_nsec) / 1000);
|
||||
if (fd_logger_self()->stats.nb_recv)
|
||||
{
|
||||
/* Ponderate in the avg */
|
||||
fd_logger_self()->stats.avg = (fd_logger_self()->stats.avg *
|
||||
fd_logger_self()->stats.nb_recv + dur) /
|
||||
(fd_logger_self()->stats.nb_recv + 1);
|
||||
/* Min, max */
|
||||
if (dur < fd_logger_self()->stats.shortest)
|
||||
fd_logger_self()->stats.shortest = dur;
|
||||
if (dur > fd_logger_self()->stats.longest)
|
||||
fd_logger_self()->stats.longest = dur;
|
||||
}
|
||||
else
|
||||
{
|
||||
fd_logger_self()->stats.shortest = dur;
|
||||
fd_logger_self()->stats.longest = dur;
|
||||
fd_logger_self()->stats.avg = dur;
|
||||
}
|
||||
if (error)
|
||||
fd_logger_self()->stats.nb_errs++;
|
||||
else
|
||||
fd_logger_self()->stats.nb_recv++;
|
||||
|
||||
CHECK_POSIX_DO( pthread_mutex_unlock(&fd_logger_self()->stats_lock), );
|
||||
|
||||
/* Display how long it took */
|
||||
if (ts.tv_nsec > mi->ts.tv_nsec)
|
||||
d_trace(3, "in %d.%06ld sec\n",
|
||||
(int)(ts.tv_sec - mi->ts.tv_sec),
|
||||
(long)(ts.tv_nsec - mi->ts.tv_nsec) / 1000);
|
||||
else
|
||||
d_trace(3, "in %d.%06ld sec\n",
|
||||
(int)(ts.tv_sec + 1 - mi->ts.tv_sec),
|
||||
(long)(1000000000 + ts.tv_nsec - mi->ts.tv_nsec) / 1000);
|
||||
|
||||
CHECK_FCT_DO( fd_msg_free(*msg), return );
|
||||
*msg = NULL;
|
||||
|
||||
pool_free_node(&pgw_gx_sess_pool, mi);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int pgw_gx_init(void)
|
||||
{
|
||||
pool_init(&pgw_gx_sess_pool, MAX_NUM_SESSION_STATE);
|
||||
|
||||
CHECK_FCT( fd_init(FD_MODE_CLIENT, pgw_self()->fd_conf_path) );
|
||||
|
||||
/* Install objects definitions for this application */
|
||||
CHECK_FCT( gx_dict_init() );
|
||||
|
||||
CHECK_FCT( fd_sess_handler_create(&pgw_gx_reg, (void *)free, NULL, NULL) );
|
||||
|
||||
/* Advertise the support for the application in the peer */
|
||||
CHECK_FCT( fd_disp_app_support(gx_application, fd_vendor, 1, 0) );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pgw_gx_final(void)
|
||||
{
|
||||
CHECK_FCT_DO( fd_sess_handler_destroy(&pgw_gx_reg, NULL), );
|
||||
|
||||
fd_final();
|
||||
|
||||
if (pool_size(&pgw_gx_sess_pool) != pool_avail(&pgw_gx_sess_pool))
|
||||
d_error("%d not freed in pgw_gx_sess_pool[%d] of S6A-SM",
|
||||
pool_size(&pgw_gx_sess_pool) - pool_avail(&pgw_gx_sess_pool),
|
||||
pool_size(&pgw_gx_sess_pool));
|
||||
|
||||
d_trace(3, "%d not freed in pgw_gx_sess_pool[%d] of S6A-SM\n",
|
||||
pool_size(&pgw_gx_sess_pool) - pool_avail(&pgw_gx_sess_pool),
|
||||
pool_size(&pgw_gx_sess_pool));
|
||||
|
||||
pool_final(&pgw_gx_sess_pool);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PGW_GX_HANDLER_H__
|
||||
#define __PGW_GX_HANDLER_H__
|
||||
|
||||
#include "core_errno.h"
|
||||
#include "gtp_tlv.h"
|
||||
|
||||
#include "pgw_context.h"
|
||||
|
||||
|
@ -9,15 +9,10 @@
|
|||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
CORE_DECLARE(int) pgw_gx_init(void);
|
||||
CORE_DECLARE(void) pgw_gx_final(void);
|
||||
|
||||
CORE_DECLARE(void) pgw_gx_send_ccr(
|
||||
gtp_xact_t *xact, pgw_sess_t *sess, c_uint32_t cc_request_type);
|
||||
CORE_DECLARE(void) pgw_gx_handle_cca()
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __PGW_GX_HANDLER_H__ */
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "pgw_context.h"
|
||||
#include "pgw_event.h"
|
||||
|
||||
#include "pgw_gx_handler.h"
|
||||
#include "pgw_fd_path.h"
|
||||
|
||||
static thread_id sm_thread;
|
||||
static void *THREAD_FUNC sm_main(thread_id id, void *data);
|
||||
|
@ -33,7 +33,7 @@ status_t pgw_initialize()
|
|||
rv = pgw_ip_pool_generate();
|
||||
if (rv != CORE_OK) return rv;
|
||||
|
||||
ret = pgw_gx_init();
|
||||
ret = pgw_fd_init();
|
||||
if (ret != 0) return CORE_ERROR;
|
||||
|
||||
rv = thread_create(&sm_thread, NULL, sm_main, NULL);
|
||||
|
@ -53,7 +53,7 @@ void pgw_terminate(void)
|
|||
thread_delete(net_thread);
|
||||
thread_delete(sm_thread);
|
||||
|
||||
pgw_gx_final();
|
||||
pgw_fd_final();
|
||||
|
||||
pgw_context_final();
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#define TRACE_MODULE _pgw_s5c_handler
|
||||
|
||||
#include "core_debug.h"
|
||||
#include "core_lib.h"
|
||||
|
||||
#include "gtp_types.h"
|
||||
|
||||
|
@ -98,11 +99,14 @@ c_int16_t pgw_pco_build(c_uint8_t *pco_buf, tlv_pco_t *tlv_pco)
|
|||
|
||||
|
||||
|
||||
void pgw_handle_create_session_request(
|
||||
void pgw_s5c_handle_create_session_request(
|
||||
gtp_xact_t *xact, pgw_sess_t *sess, gtp_create_session_request_t *req)
|
||||
{
|
||||
gtp_f_teid_t *sgw_s5c_teid, *sgw_s5u_teid;
|
||||
pgw_bearer_t *bearer = NULL;
|
||||
gtp_bearer_qos_t bearer_qos;
|
||||
gtp_ambr_t *ambr = NULL;
|
||||
gtp_uli_t uli;
|
||||
|
||||
d_assert(xact, return, "Null param");
|
||||
d_assert(sess, return, "Null param");
|
||||
|
@ -110,6 +114,12 @@ void pgw_handle_create_session_request(
|
|||
bearer = pgw_default_bearer_in_sess(sess);
|
||||
d_assert(bearer, return, "Null param");
|
||||
|
||||
if (req->sender_f_teid_for_control_plane.presence == 0)
|
||||
{
|
||||
d_error("No IMSI");
|
||||
return;
|
||||
}
|
||||
|
||||
if (req->sender_f_teid_for_control_plane.presence == 0)
|
||||
{
|
||||
d_error("No TEID");
|
||||
|
@ -125,11 +135,26 @@ void pgw_handle_create_session_request(
|
|||
d_error("No EPS Bearer ID");
|
||||
return;
|
||||
}
|
||||
if (req->bearer_contexts_to_be_created.bearer_level_qos.presence == 0)
|
||||
{
|
||||
d_error("No EPS Bearer QoS");
|
||||
return;
|
||||
}
|
||||
if (req->bearer_contexts_to_be_created.s5_s8_u_sgw_f_teid.presence == 0)
|
||||
{
|
||||
d_error("No TEID");
|
||||
return;
|
||||
}
|
||||
if (req->user_location_information.presence == 0)
|
||||
{
|
||||
d_error("No User Location Inforamtion");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set IMSI */
|
||||
sess->imsi_len = req->imsi.len;
|
||||
memcpy(sess->imsi, req->imsi.data, sess->imsi_len);
|
||||
core_buffer_to_bcd(sess->imsi, sess->imsi_len, sess->imsi_bcd);
|
||||
|
||||
/* Receive Control Plane(DL) : SGW-S5C */
|
||||
sgw_s5c_teid = req->sender_f_teid_for_control_plane.data;
|
||||
|
@ -141,11 +166,37 @@ void pgw_handle_create_session_request(
|
|||
bearer->sgw_s5u_teid = ntohl(sgw_s5u_teid->teid);
|
||||
bearer->sgw_s5u_addr = sgw_s5u_teid->ipv4_addr;
|
||||
|
||||
d_assert(gtp_parse_bearer_qos(&bearer_qos,
|
||||
&req->bearer_contexts_to_be_created.bearer_level_qos) ==
|
||||
req->bearer_contexts_to_be_created.bearer_level_qos.len, return,);
|
||||
sess->pdn.qos.qci = bearer_qos.qci;
|
||||
sess->pdn.qos.arp.priority_level = bearer_qos.priority_level;
|
||||
sess->pdn.qos.arp.pre_emption_capability =
|
||||
bearer_qos.pre_emption_capability;
|
||||
sess->pdn.qos.arp.pre_emption_vulnerability =
|
||||
bearer_qos.pre_emption_vulnerability;
|
||||
|
||||
/* Set AMBR if available */
|
||||
if (req->aggregate_maximum_bit_rate.presence)
|
||||
{
|
||||
ambr = req->aggregate_maximum_bit_rate.data;
|
||||
sess->pdn.ambr.downlink = ntohl(ambr->downlink);
|
||||
sess->pdn.ambr.uplink = ntohl(ambr->uplink);
|
||||
}
|
||||
|
||||
/* Set User Location Information */
|
||||
d_assert(gtp_parse_uli(&uli, &req->user_location_information) ==
|
||||
req->user_location_information.len, return,);
|
||||
memcpy(&sess->tai.plmn_id, &uli.tai.plmn_id, sizeof(uli.tai.plmn_id));
|
||||
sess->tai.tac = uli.tai.tac;
|
||||
memcpy(&sess->e_cgi.plmn_id, &uli.e_cgi.plmn_id, sizeof(uli.e_cgi.plmn_id));
|
||||
sess->e_cgi.cell_id = uli.e_cgi.cell_id;
|
||||
|
||||
d_trace(3, "[GTP] Create Session Reqeust : "
|
||||
"SGW[%d] --> PGW[%d]\n", sess->sgw_s5c_teid, sess->pgw_s5c_teid);
|
||||
}
|
||||
|
||||
void pgw_handle_create_session_response(gtp_xact_t *xact, pgw_sess_t *sess)
|
||||
void pgw_s5c_handle_create_session_response(gtp_xact_t *xact, pgw_sess_t *sess)
|
||||
{
|
||||
status_t rv;
|
||||
pkbuf_t *pkbuf;
|
||||
|
@ -192,11 +243,11 @@ void pgw_handle_create_session_response(gtp_xact_t *xact, pgw_sess_t *sess)
|
|||
len = GTP_F_TEID_IPV4_LEN;
|
||||
|
||||
d_assert(sess->ip_pool, return, "No IP Pool");
|
||||
sess->paa.pdn_type = GTP_PDN_TYPE_IPV4;
|
||||
sess->paa.ipv4_addr = sess->ip_pool->ue_addr;
|
||||
sess->pdn.paa.pdn_type = GTP_PDN_TYPE_IPV4;
|
||||
sess->pdn.paa.ipv4_addr = sess->ip_pool->ue_addr;
|
||||
|
||||
rsp->pdn_address_allocation.presence = 1;
|
||||
rsp->pdn_address_allocation.data = &sess->paa;
|
||||
rsp->pdn_address_allocation.data = &sess->pdn.paa;
|
||||
rsp->pdn_address_allocation.len = PAA_IPV4_LEN;
|
||||
|
||||
rsp->apn_restriction.presence = 1;
|
||||
|
@ -232,12 +283,12 @@ void pgw_handle_create_session_response(gtp_xact_t *xact, pgw_sess_t *sess)
|
|||
pgw_s5c_send_to_sgw(xact, type, sess->sgw_s5c_teid, pkbuf);
|
||||
}
|
||||
|
||||
void pgw_handle_delete_session_request(
|
||||
void pgw_s5c_handle_delete_session_request(
|
||||
gtp_xact_t *xact, pgw_sess_t *sess, gtp_delete_session_request_t *req)
|
||||
{
|
||||
}
|
||||
|
||||
void pgw_handle_delete_session_response(gtp_xact_t *xact, pgw_sess_t *sess)
|
||||
void pgw_s5c_handle_delete_session_response(gtp_xact_t *xact, pgw_sess_t *sess)
|
||||
{
|
||||
status_t rv;
|
||||
pkbuf_t *pkbuf;
|
||||
|
|
|
@ -9,13 +9,13 @@
|
|||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
CORE_DECLARE(void) pgw_handle_create_session_request(
|
||||
CORE_DECLARE(void) pgw_s5c_handle_create_session_request(
|
||||
gtp_xact_t *xact, pgw_sess_t *sess, gtp_create_session_request_t *req);
|
||||
CORE_DECLARE(void) pgw_handle_create_session_response(
|
||||
CORE_DECLARE(void) pgw_s5c_handle_create_session_response(
|
||||
gtp_xact_t *xact, pgw_sess_t *sess);
|
||||
CORE_DECLARE(void) pgw_handle_delete_session_request(
|
||||
CORE_DECLARE(void) pgw_s5c_handle_delete_session_request(
|
||||
gtp_xact_t *xact, pgw_sess_t *sess, gtp_delete_session_request_t *req);
|
||||
CORE_DECLARE(void) pgw_handle_delete_session_response(
|
||||
CORE_DECLARE(void) pgw_s5c_handle_delete_session_response(
|
||||
gtp_xact_t *xact, pgw_sess_t *sess);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "pgw_event.h"
|
||||
#include "pgw_gtp_path.h"
|
||||
#include "pgw_s5c_handler.h"
|
||||
#include "pgw_gx_handler.h"
|
||||
#include "pgw_fd_path.h"
|
||||
|
||||
void pgw_state_initial(fsm_t *s, event_t *e)
|
||||
{
|
||||
|
@ -121,13 +121,13 @@ void pgw_state_operational(fsm_t *s, event_t *e)
|
|||
switch(type)
|
||||
{
|
||||
case GTP_CREATE_SESSION_REQUEST_TYPE:
|
||||
pgw_handle_create_session_request(
|
||||
pgw_s5c_handle_create_session_request(
|
||||
xact, sess, >p_message.create_session_request);
|
||||
pgw_gx_send_ccr(xact, sess,
|
||||
GX_CC_REQUEST_TYPE_INITIAL_REQUEST);
|
||||
break;
|
||||
case GTP_DELETE_SESSION_REQUEST_TYPE:
|
||||
pgw_handle_delete_session_request(
|
||||
pgw_s5c_handle_delete_session_request(
|
||||
xact, sess, >p_message.delete_session_request);
|
||||
pgw_gx_send_ccr(xact, sess,
|
||||
GX_CC_REQUEST_TYPE_TERMINATION_REQUEST);
|
||||
|
@ -167,18 +167,19 @@ void pgw_state_operational(fsm_t *s, event_t *e)
|
|||
if (result_code != ER_DIAMETER_SUCCESS)
|
||||
{
|
||||
d_error("Not impleneted");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
switch(event_get_param4(e))
|
||||
{
|
||||
case GX_CC_REQUEST_TYPE_INITIAL_REQUEST:
|
||||
{
|
||||
pgw_handle_create_session_response(xact, sess);
|
||||
pgw_s5c_handle_create_session_response(xact, sess);
|
||||
|
||||
break;
|
||||
}
|
||||
case GX_CC_REQUEST_TYPE_TERMINATION_REQUEST:
|
||||
{
|
||||
pgw_handle_delete_session_response(xact, sess);
|
||||
pgw_s5c_handle_delete_session_response(xact, sess);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
Loading…
Reference in New Issue