GX-CCR message build done

This commit is contained in:
Sukchan Lee 2017-08-23 00:51:57 +09:00
parent 17dc308aa2
commit 0e7196c9c1
25 changed files with 785 additions and 390 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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 =

View File

@ -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);

View File

@ -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 \

View File

@ -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;

View File

@ -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();

18
src/pcrf/pcrf_fd_path.h Normal file
View File

@ -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__ */

View File

@ -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__ */

View File

@ -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();

View File

@ -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 \

View File

@ -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);

View File

@ -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;

493
src/pgw/pgw_fd_path.c Normal file
View File

@ -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);
}

23
src/pgw/pgw_fd_path.h Normal file
View File

@ -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__ */

View File

@ -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);
}

View File

@ -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__ */

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -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, &gtp_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, &gtp_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: