forked from acouzens/open5gs
Volte QoS is basically derived by IMS instead of EPC.
If the QoS informaton is provided from IMS, we'll use WEBUI QoS value
This commit is contained in:
parent
131babeddc
commit
46f85d9fc8
|
@ -207,6 +207,16 @@ typedef struct _flow_t {
|
|||
c_int8_t *description;
|
||||
} flow_t;
|
||||
|
||||
#define FLOW_FREE(__fLOW) \
|
||||
do { \
|
||||
if ((__fLOW)->description) \
|
||||
{ \
|
||||
CORE_FREE((__fLOW)->description); \
|
||||
} \
|
||||
else \
|
||||
d_assert(0,, "Null param"); \
|
||||
} while(0)
|
||||
|
||||
/**********************************
|
||||
* PCC Rule Structure */
|
||||
typedef struct _pcc_rule_t {
|
||||
|
@ -231,6 +241,24 @@ typedef struct _pcc_rule_t {
|
|||
qos_t qos;
|
||||
} pcc_rule_t;
|
||||
|
||||
#define PCC_RULE_FREE(__pCCrULE) \
|
||||
do { \
|
||||
int __pCCrULE_iNDEX; \
|
||||
d_assert((__pCCrULE), break,); \
|
||||
if ((__pCCrULE)->name) \
|
||||
{ \
|
||||
CORE_FREE((__pCCrULE)->name); \
|
||||
} \
|
||||
else \
|
||||
d_assert(0,, "Null param"); \
|
||||
for (__pCCrULE_iNDEX = 0; \
|
||||
__pCCrULE_iNDEX < (__pCCrULE)->num_of_flow; __pCCrULE_iNDEX++) \
|
||||
{ \
|
||||
FLOW_FREE(&((__pCCrULE)->flow[__pCCrULE_iNDEX])); \
|
||||
} \
|
||||
(__pCCrULE)->num_of_flow = 0; \
|
||||
} while(0)
|
||||
|
||||
/**********************************
|
||||
* PDN Structure */
|
||||
typedef struct _pdn_t {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "core_debug.h"
|
||||
#include "core_lib.h"
|
||||
#include "core_pkbuf.h"
|
||||
|
||||
#include "3gpp_types.h"
|
||||
|
||||
|
|
|
@ -7,31 +7,12 @@
|
|||
|
||||
void gx_message_free(gx_message_t *gx_message)
|
||||
{
|
||||
int i, j;
|
||||
int i;
|
||||
|
||||
d_assert(gx_message, return,);
|
||||
|
||||
for (i = 0; i < gx_message->num_of_pcc_rule; i++)
|
||||
{
|
||||
pcc_rule_t *pcc_rule = &gx_message->pcc_rule[i];
|
||||
|
||||
if (pcc_rule->name)
|
||||
{
|
||||
CORE_FREE(pcc_rule->name)
|
||||
}
|
||||
else
|
||||
d_assert(0,, "Null param");
|
||||
|
||||
for (j = 0; j < pcc_rule->num_of_flow; j++)
|
||||
{
|
||||
flow_t *flow = &pcc_rule->flow[j];
|
||||
|
||||
if (flow->description)
|
||||
{
|
||||
CORE_FREE(flow->description);
|
||||
}
|
||||
else
|
||||
d_assert(0,, "Null param");
|
||||
}
|
||||
PCC_RULE_FREE(&gx_message->pcc_rule[i]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ extern "C" {
|
|||
#define RX_AVP_CODE_MEDIA_TYPE (520)
|
||||
#define RX_AVP_CODE_MAX_REQUESTED_BANDWIDTH_DL (515)
|
||||
#define RX_AVP_CODE_MAX_REQUESTED_BANDWIDTH_UL (516)
|
||||
#define RX_AVP_CODE_RR_BANDWIDTH (521)
|
||||
#define RX_AVP_CODE_RS_BANDWIDTH (522)
|
||||
#define RX_AVP_CODE_MIN_REQUESTED_BANDWIDTH_DL (534)
|
||||
#define RX_AVP_CODE_MIN_REQUESTED_BANDWIDTH_UL (535)
|
||||
#define RX_AVP_CODE_MEDIA_COMPONENT_NUMBER (518)
|
||||
|
|
|
@ -29,8 +29,12 @@ typedef struct _rx_media_component_t {
|
|||
#define RX_MEDIA_TYPE_OTHER 0xFFFFFFFF
|
||||
c_uint32_t media_type;
|
||||
|
||||
bitrate_t mbr; /* Maxmimum Bit Rate (MBR) */
|
||||
bitrate_t gbr; /* Guaranteed Bit Rate (GBR) */
|
||||
c_uint64_t max_requested_bandwidth_dl;
|
||||
c_uint64_t max_requested_bandwidth_ul;
|
||||
c_uint64_t min_requested_bandwidth_dl;
|
||||
c_uint64_t min_requested_bandwidth_ul;
|
||||
c_uint64_t rr_bandwidth;
|
||||
c_uint64_t rs_bandwidth;
|
||||
|
||||
#define MAX_NUM_OF_MEDIA_SUB_COMPONENT 8
|
||||
rx_media_sub_component_t sub[MAX_NUM_OF_MEDIA_SUB_COMPONENT];
|
||||
|
|
|
@ -18,8 +18,9 @@ struct rx_sess_state {
|
|||
lnode_t node;
|
||||
|
||||
os0_t sid; /* Rx Session-Id */
|
||||
c_int8_t *name[MAX_NUM_OF_PCC_RULE]; /* PCC Rule Name */
|
||||
int num_of_name;
|
||||
|
||||
pcc_rule_t pcc_rule[MAX_NUM_OF_PCC_RULE];
|
||||
int num_of_pcc_rule;
|
||||
|
||||
struct sess_state *gx;
|
||||
};
|
||||
|
@ -52,10 +53,17 @@ pool_declare(pcrf_gx_sess_pool, struct sess_state, MAX_POOL_OF_DIAMETER_SESS);
|
|||
pool_declare(pcrf_gx_rx_sess_pool,
|
||||
struct rx_sess_state, MAX_POOL_OF_DIAMETER_SESS);
|
||||
|
||||
static status_t encode_pcc_rule_definition(
|
||||
struct avp *avp, pcc_rule_t *pcc_rule);
|
||||
static void pcrf_gx_raa_cb(void *data, struct msg **msg);
|
||||
|
||||
static status_t encode_pcc_rule_definition(
|
||||
struct avp *avp, pcc_rule_t *pcc_rule, int flow_presence);
|
||||
static int matched_flow(
|
||||
pcc_rule_t *pcc_rule, rx_media_component_t *media_component);
|
||||
static status_t install_flow(
|
||||
pcc_rule_t *pcc_rule, rx_media_component_t *media_component);
|
||||
static status_t update_qos(
|
||||
pcc_rule_t *pcc_rule, rx_media_component_t *media_component);
|
||||
|
||||
static __inline__ struct sess_state *new_state(os0_t sid)
|
||||
{
|
||||
struct sess_state *new = NULL;
|
||||
|
@ -103,10 +111,9 @@ static status_t remove_rx_state(struct rx_sess_state *rx_sess_data)
|
|||
d_assert(rx_sess_data, return CORE_ERROR,);
|
||||
gx = rx_sess_data->gx;
|
||||
|
||||
for (i = 0; i < rx_sess_data->num_of_name; i++)
|
||||
for (i = 0; i < rx_sess_data->num_of_pcc_rule; i++)
|
||||
{
|
||||
d_assert(rx_sess_data->name[i],,);
|
||||
CORE_FREE(rx_sess_data->name[i]);
|
||||
PCC_RULE_FREE(&rx_sess_data->pcc_rule[i]);
|
||||
}
|
||||
|
||||
if (rx_sess_data->sid)
|
||||
|
@ -207,6 +214,8 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp,
|
|||
c_uint32_t cc_request_number = 0;
|
||||
c_uint32_t result_code = FD_DIAMETER_MISSING_AVP;
|
||||
|
||||
d_trace(3, "[PCRF] Credit-Control-Request : PGW --> PCRF\n");
|
||||
|
||||
d_assert(msg, return EINVAL,);
|
||||
|
||||
ret = fd_sess_state_retrieve(pcrf_gx_reg, sess, &sess_data);
|
||||
|
@ -440,7 +449,7 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp,
|
|||
charging_rule = 1;
|
||||
}
|
||||
|
||||
rv = encode_pcc_rule_definition(avp, pcc_rule);
|
||||
rv = encode_pcc_rule_definition(avp, pcc_rule, 1);
|
||||
d_assert(rv == CORE_OK, return EINVAL,);
|
||||
}
|
||||
}
|
||||
|
@ -649,7 +658,8 @@ status_t pcrf_gx_send_rar(
|
|||
c_uint8_t *gx_sid, c_uint8_t *rx_sid, rx_message_t *rx_message)
|
||||
{
|
||||
status_t rv;
|
||||
int ret = 0, i, j, k;
|
||||
int ret = 0, i, j;
|
||||
int count = 0;
|
||||
|
||||
struct msg *req = NULL;
|
||||
struct avp *avp, *avpch1;
|
||||
|
@ -667,6 +677,8 @@ status_t pcrf_gx_send_rar(
|
|||
d_assert(rx_sid, return CORE_ERROR,);
|
||||
d_assert(rx_message, return CORE_ERROR,);
|
||||
|
||||
d_trace(3, "[PCRF] Re-Auth-Request : PCRF -> PGW\n");
|
||||
|
||||
/* Initialize Message */
|
||||
memset(&gx_message, 0, sizeof(gx_message_t));
|
||||
|
||||
|
@ -740,7 +752,9 @@ status_t pcrf_gx_send_rar(
|
|||
/* Match Media-Component with PCC Rule */
|
||||
for (i = 0; i < rx_message->num_of_media_component; i++)
|
||||
{
|
||||
int flow_presence = 0;
|
||||
pcc_rule_t *pcc_rule = NULL;
|
||||
pcc_rule_t *db_pcc_rule = NULL;
|
||||
c_uint8_t qci = 0;
|
||||
rx_media_component_t *media_component =
|
||||
&rx_message->media_component[i];
|
||||
|
@ -768,128 +782,109 @@ status_t pcrf_gx_send_rar(
|
|||
|
||||
for (j = 0; j < gx_message.num_of_pcc_rule; j++)
|
||||
{
|
||||
pcc_rule = &gx_message.pcc_rule[j];
|
||||
if (pcc_rule->qos.qci == qci)
|
||||
if (gx_message.pcc_rule[j].qos.qci == qci)
|
||||
{
|
||||
db_pcc_rule = &gx_message.pcc_rule[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pcc_rule)
|
||||
if (!db_pcc_rule)
|
||||
{
|
||||
d_error("CHECK WEBUI : No PCC Rule [QCI:%d]", qci);
|
||||
d_error("CHECK WEBUI : No PCC Rule in DB [QCI:%d]", qci);
|
||||
d_error("Please add PCC Rule using WEBUI");
|
||||
rx_message->result_code =
|
||||
RX_DIAMETER_REQUESTED_SERVICE_NOT_AUTHORIZED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check WEBUI static dedicated bearer */
|
||||
if (pcc_rule->num_of_flow)
|
||||
for (j = 0; j < rx_sess_data->num_of_pcc_rule; j++)
|
||||
{
|
||||
d_warn("Dedicated bearer has already been activated by WEBUI");
|
||||
d_warn("Modify dedicated bearer is initiated by IMS");
|
||||
|
||||
for (j = 0; j < pcc_rule->num_of_flow; j++)
|
||||
if (rx_sess_data->pcc_rule[j].qos.qci == qci)
|
||||
{
|
||||
flow_t *flow = &pcc_rule->flow[j];
|
||||
pcc_rule = &rx_sess_data->pcc_rule[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flow->description)
|
||||
{
|
||||
CORE_FREE(flow->description);
|
||||
}
|
||||
else
|
||||
d_assert(0,, "Null param");
|
||||
if (!pcc_rule)
|
||||
{
|
||||
pcc_rule =
|
||||
&rx_sess_data->pcc_rule[rx_sess_data->num_of_pcc_rule];
|
||||
|
||||
/* Device PCC Rule Info from DB Profile */
|
||||
pcc_rule->name = core_strdup(db_pcc_rule->name);
|
||||
d_assert(pcc_rule->name, return CORE_ERROR,);
|
||||
|
||||
memcpy(&pcc_rule->qos, &db_pcc_rule->qos, sizeof(qos_t));
|
||||
|
||||
pcc_rule->flow_status = db_pcc_rule->flow_status;
|
||||
pcc_rule->precedence = db_pcc_rule->precedence;
|
||||
|
||||
/* Install Flow */
|
||||
flow_presence = 1;
|
||||
rv = install_flow(pcc_rule, media_component);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
rx_message->result_code = RX_DIAMETER_FILTER_RESTRICTIONS;
|
||||
d_error("install_flow() failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
pcc_rule->num_of_flow = 0;
|
||||
rx_sess_data->num_of_pcc_rule++;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_assert(strcmp(pcc_rule->name, db_pcc_rule->name) == 0,
|
||||
return CORE_ERROR, "Mismatch Rule Name [%s:%s]",
|
||||
pcc_rule->name, db_pcc_rule->name);
|
||||
|
||||
/* Update QoS parameter */
|
||||
if (media_component->mbr.uplink)
|
||||
{
|
||||
if (pcc_rule->qos.mbr.uplink)
|
||||
pcc_rule->qos.mbr.uplink =
|
||||
c_min(pcc_rule->qos.mbr.uplink, media_component->mbr.uplink);
|
||||
else
|
||||
pcc_rule->qos.mbr.uplink = media_component->mbr.uplink;
|
||||
}
|
||||
if (media_component->mbr.downlink)
|
||||
{
|
||||
if (pcc_rule->qos.mbr.downlink)
|
||||
pcc_rule->qos.mbr.downlink =
|
||||
c_min(pcc_rule->qos.mbr.downlink, media_component->mbr.downlink);
|
||||
else
|
||||
pcc_rule->qos.mbr.downlink = media_component->mbr.downlink;
|
||||
}
|
||||
if (media_component->gbr.uplink)
|
||||
{
|
||||
if (pcc_rule->qos.gbr.uplink)
|
||||
pcc_rule->qos.gbr.uplink =
|
||||
c_min(pcc_rule->qos.gbr.uplink, media_component->gbr.uplink);
|
||||
else
|
||||
pcc_rule->qos.gbr.uplink = media_component->gbr.uplink;
|
||||
}
|
||||
if (media_component->gbr.downlink)
|
||||
{
|
||||
if (pcc_rule->qos.gbr.downlink)
|
||||
pcc_rule->qos.gbr.downlink =
|
||||
c_min(pcc_rule->qos.gbr.downlink, media_component->gbr.downlink);
|
||||
else
|
||||
pcc_rule->qos.gbr.downlink = media_component->gbr.downlink;
|
||||
}
|
||||
|
||||
for (j = 0; j < media_component->num_of_sub; j++)
|
||||
{
|
||||
rx_media_sub_component_t *sub = &media_component->sub[j];
|
||||
|
||||
if (sub->flow_number == 0)
|
||||
/* Check Flow */
|
||||
count = matched_flow(pcc_rule, media_component);
|
||||
if (count == -1)
|
||||
{
|
||||
continue;
|
||||
rx_message->result_code = RX_DIAMETER_FILTER_RESTRICTIONS;
|
||||
d_error("matched_flow() failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (k = 0; k < sub->num_of_flow; k++)
|
||||
if (pcc_rule->num_of_flow != count)
|
||||
{
|
||||
int len;
|
||||
flow_t *gx_flow = &pcc_rule->flow[pcc_rule->num_of_flow];
|
||||
flow_t *rx_flow = &sub->flow[k];
|
||||
|
||||
if (!strncmp(rx_flow->description,
|
||||
"permit out", strlen("permit out")))
|
||||
/* Re-install Flow */
|
||||
flow_presence = 1;
|
||||
rv = install_flow(pcc_rule, media_component);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
gx_flow->direction = FLOW_DOWNLINK_ONLY;
|
||||
|
||||
len = strlen(rx_flow->description)+1;
|
||||
gx_flow->description = core_malloc(len);
|
||||
core_cpystrn(gx_flow->description,
|
||||
rx_flow->description, len);
|
||||
}
|
||||
else if (!strncmp(rx_flow->description,
|
||||
"permit in", strlen("permit in")))
|
||||
{
|
||||
gx_flow->direction = FLOW_UPLINK_ONLY;
|
||||
|
||||
/* 'permit in' should be changed
|
||||
* 'permit out' in Gx Diameter */
|
||||
len = strlen(rx_flow->description)+2;
|
||||
gx_flow->description = core_malloc(len);
|
||||
strcpy(gx_flow->description, "permit out");
|
||||
strcat(gx_flow->description,
|
||||
&rx_flow->description[strlen("permit in")]);
|
||||
d_assert(len == strlen(gx_flow->description)+1, goto out,);
|
||||
}
|
||||
else
|
||||
{
|
||||
d_error("Invalid Flow Descripton : [%s]",
|
||||
rx_flow->description);
|
||||
rx_message->result_code = RX_DIAMETER_FILTER_RESTRICTIONS;
|
||||
rx_message->result_code =
|
||||
RX_DIAMETER_FILTER_RESTRICTIONS;
|
||||
d_error("install_flow() failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
pcc_rule->num_of_flow++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Update QoS */
|
||||
rv = update_qos(pcc_rule, media_component);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
rx_message->result_code =
|
||||
RX_DIAMETER_REQUESTED_SERVICE_NOT_AUTHORIZED;
|
||||
d_error("update_qos() failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* if we failed to get QoS from IMS, apply WEBUI QoS */
|
||||
if (pcc_rule->qos.mbr.downlink == 0)
|
||||
pcc_rule->qos.mbr.downlink = db_pcc_rule->qos.mbr.downlink;
|
||||
if (pcc_rule->qos.mbr.uplink == 0)
|
||||
pcc_rule->qos.mbr.uplink = db_pcc_rule->qos.mbr.uplink;
|
||||
if (pcc_rule->qos.gbr.downlink == 0)
|
||||
pcc_rule->qos.gbr.downlink = db_pcc_rule->qos.gbr.downlink;
|
||||
if (pcc_rule->qos.gbr.uplink == 0)
|
||||
pcc_rule->qos.gbr.uplink = db_pcc_rule->qos.gbr.uplink;
|
||||
|
||||
if (charging_rule == 0)
|
||||
{
|
||||
ret = fd_msg_avp_new(gx_charging_rule_install, 0, &avp);
|
||||
|
@ -897,15 +892,8 @@ status_t pcrf_gx_send_rar(
|
|||
charging_rule = 1;
|
||||
}
|
||||
|
||||
rv = encode_pcc_rule_definition(avp, pcc_rule);
|
||||
rv = encode_pcc_rule_definition(avp, pcc_rule, flow_presence);
|
||||
d_assert(rv == CORE_OK, return CORE_ERROR,);
|
||||
|
||||
/* Store PCC Rule Name in Rx session state */
|
||||
rx_sess_data->name[rx_sess_data->num_of_name]
|
||||
= core_strdup(pcc_rule->name);
|
||||
d_assert(rx_sess_data->name[rx_sess_data->num_of_name],
|
||||
return CORE_ERROR,);
|
||||
rx_sess_data->num_of_name++;
|
||||
}
|
||||
|
||||
if (charging_rule == 1)
|
||||
|
@ -919,9 +907,9 @@ status_t pcrf_gx_send_rar(
|
|||
{
|
||||
d_assert(rx_sess_data, return CORE_ERROR,);
|
||||
|
||||
for (i = 0; i < rx_sess_data->num_of_name; i++)
|
||||
for (i = 0; i < rx_sess_data->num_of_pcc_rule; i++)
|
||||
{
|
||||
d_assert(rx_sess_data->name[i],,);
|
||||
d_assert(rx_sess_data->pcc_rule[i].name,,);
|
||||
|
||||
if (charging_rule == 0)
|
||||
{
|
||||
|
@ -932,8 +920,8 @@ status_t pcrf_gx_send_rar(
|
|||
|
||||
ret = fd_msg_avp_new(gx_charging_rule_name, 0, &avpch1);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
val.os.data = (c_uint8_t *)rx_sess_data->name[i];
|
||||
val.os.len = strlen(rx_sess_data->name[i]);
|
||||
val.os.data = (c_uint8_t *)rx_sess_data->pcc_rule[i].name;
|
||||
val.os.len = strlen(rx_sess_data->pcc_rule[i].name);
|
||||
ret = fd_msg_avp_setvalue(avpch1, &val);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
|
@ -1021,8 +1009,6 @@ status_t pcrf_gx_send_rar(
|
|||
fd_logger_self()->stats.nb_sent++;
|
||||
d_assert(pthread_mutex_unlock(&fd_logger_self()->stats_lock) == 0,, );
|
||||
|
||||
d_trace(3, "[Gx] Re-Auth-Request : PCRF --> PGW\n");
|
||||
|
||||
/* Set no error */
|
||||
rx_message->result_code = ER_DIAMETER_SUCCESS;
|
||||
|
||||
|
@ -1055,6 +1041,8 @@ static void pcrf_gx_raa_cb(void *data, struct msg **msg)
|
|||
|
||||
c_uint32_t result_code;
|
||||
|
||||
d_trace(3, "[PCRF] Re-Auth-Answer : PGW --> PCRF\n");
|
||||
|
||||
ret = clock_gettime(CLOCK_REALTIME, &ts);
|
||||
d_assert(ret == 0, return,);
|
||||
|
||||
|
@ -1067,8 +1055,6 @@ static void pcrf_gx_raa_cb(void *data, struct msg **msg)
|
|||
d_assert(ret == 0, return,);
|
||||
d_assert(sess_data && (void *)sess_data == data, return, );
|
||||
|
||||
d_trace(3, "[Gx] Re-Auth-Answer : PGW --> PCRF\n");
|
||||
|
||||
/* Value of Result Code */
|
||||
ret = fd_msg_search_avp(*msg, fd_result_code, &avp);
|
||||
d_assert(ret == 0, return,);
|
||||
|
@ -1247,7 +1233,7 @@ void pcrf_gx_final(void)
|
|||
}
|
||||
|
||||
static status_t encode_pcc_rule_definition(
|
||||
struct avp *avp, pcc_rule_t *pcc_rule)
|
||||
struct avp *avp, pcc_rule_t *pcc_rule, int flow_presence)
|
||||
{
|
||||
struct avp *avpch1, *avpch2, *avpch3, *avpch4;
|
||||
union avp_value val;
|
||||
|
@ -1267,32 +1253,35 @@ static status_t encode_pcc_rule_definition(
|
|||
ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
|
||||
for (i = 0; i < pcc_rule->num_of_flow; i++)
|
||||
if (flow_presence == 1)
|
||||
{
|
||||
flow_t *flow = &pcc_rule->flow[i];
|
||||
for (i = 0; i < pcc_rule->num_of_flow; i++)
|
||||
{
|
||||
flow_t *flow = &pcc_rule->flow[i];
|
||||
|
||||
ret = fd_msg_avp_new(gx_flow_information, 0, &avpch2);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
ret = fd_msg_avp_new(gx_flow_information, 0, &avpch2);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
|
||||
ret = fd_msg_avp_new(gx_flow_direction, 0, &avpch3);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
val.i32 = flow->direction;
|
||||
ret = fd_msg_avp_setvalue(avpch3, &val);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
ret = fd_msg_avp_add(avpch2, MSG_BRW_LAST_CHILD, avpch3);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
ret = fd_msg_avp_new(gx_flow_direction, 0, &avpch3);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
val.i32 = flow->direction;
|
||||
ret = fd_msg_avp_setvalue(avpch3, &val);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
ret = fd_msg_avp_add(avpch2, MSG_BRW_LAST_CHILD, avpch3);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
|
||||
ret = fd_msg_avp_new(gx_flow_description, 0, &avpch3);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
val.os.data = (c_uint8_t *)flow->description;
|
||||
val.os.len = strlen(flow->description);
|
||||
ret = fd_msg_avp_setvalue(avpch3, &val);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
ret = fd_msg_avp_add(avpch2, MSG_BRW_LAST_CHILD, avpch3);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
ret = fd_msg_avp_new(gx_flow_description, 0, &avpch3);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
val.os.data = (c_uint8_t *)flow->description;
|
||||
val.os.len = strlen(flow->description);
|
||||
ret = fd_msg_avp_setvalue(avpch3, &val);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
ret = fd_msg_avp_add(avpch2, MSG_BRW_LAST_CHILD, avpch3);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
|
||||
ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
}
|
||||
}
|
||||
|
||||
ret = fd_msg_avp_new(gx_flow_status, 0, &avpch2);
|
||||
|
@ -1404,3 +1393,322 @@ static status_t encode_pcc_rule_definition(
|
|||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
static status_t flow_rx_to_gx(flow_t *rx_flow, flow_t *gx_flow)
|
||||
{
|
||||
int len;
|
||||
|
||||
d_assert(rx_flow, return CORE_ERROR,);
|
||||
d_assert(gx_flow, return CORE_ERROR,);
|
||||
|
||||
if (!strncmp(rx_flow->description,
|
||||
"permit out", strlen("permit out")))
|
||||
{
|
||||
gx_flow->direction = FLOW_DOWNLINK_ONLY;
|
||||
|
||||
len = strlen(rx_flow->description)+1;
|
||||
gx_flow->description = core_malloc(len);
|
||||
core_cpystrn(gx_flow->description, rx_flow->description, len);
|
||||
}
|
||||
else if (!strncmp(rx_flow->description,
|
||||
"permit in", strlen("permit in")))
|
||||
{
|
||||
gx_flow->direction = FLOW_UPLINK_ONLY;
|
||||
|
||||
/* 'permit in' should be changed
|
||||
* 'permit out' in Gx Diameter */
|
||||
len = strlen(rx_flow->description)+2;
|
||||
gx_flow->description = core_malloc(len);
|
||||
strcpy(gx_flow->description, "permit out");
|
||||
strcat(gx_flow->description,
|
||||
&rx_flow->description[strlen("permit in")]);
|
||||
d_assert(len == strlen(gx_flow->description)+1, return CORE_ERROR,);
|
||||
}
|
||||
else
|
||||
{
|
||||
d_error("Invalid Flow Descripton : [%s]", rx_flow->description);
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
static int matched_flow(
|
||||
pcc_rule_t *pcc_rule, rx_media_component_t *media_component)
|
||||
{
|
||||
status_t rv;
|
||||
int i, j, k;
|
||||
int matched = 0;
|
||||
int new = 0;
|
||||
|
||||
d_assert(pcc_rule, return CORE_ERROR,);
|
||||
d_assert(media_component, return CORE_ERROR,);
|
||||
|
||||
for (i = 0; i < media_component->num_of_sub; i++)
|
||||
{
|
||||
rx_media_sub_component_t *sub = &media_component->sub[i];
|
||||
|
||||
if (sub->flow_number == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < sub->num_of_flow; j++)
|
||||
{
|
||||
new++;
|
||||
}
|
||||
}
|
||||
|
||||
if (new == 0)
|
||||
{
|
||||
/* No new flow in Media-Component */
|
||||
return pcc_rule->num_of_flow;
|
||||
}
|
||||
|
||||
for (i = 0; i < media_component->num_of_sub; i++)
|
||||
{
|
||||
rx_media_sub_component_t *sub = &media_component->sub[i];
|
||||
|
||||
if (sub->flow_number == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < sub->num_of_flow; j++)
|
||||
{
|
||||
flow_t gx_flow;
|
||||
flow_t *rx_flow = &sub->flow[j];
|
||||
|
||||
rv = flow_rx_to_gx(rx_flow, &gx_flow);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("flow reformatting error");
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
for (k = 0; k < pcc_rule->num_of_flow; k++)
|
||||
{
|
||||
if (gx_flow.direction == pcc_rule->flow[k].direction &&
|
||||
!strcmp(gx_flow.description, pcc_rule->flow[k].description))
|
||||
{
|
||||
matched++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FLOW_FREE(&gx_flow);
|
||||
}
|
||||
}
|
||||
|
||||
return matched;
|
||||
}
|
||||
|
||||
static status_t install_flow(
|
||||
pcc_rule_t *pcc_rule, rx_media_component_t *media_component)
|
||||
{
|
||||
status_t rv;
|
||||
int i, j;
|
||||
|
||||
d_assert(pcc_rule, return CORE_ERROR,);
|
||||
d_assert(media_component, return CORE_ERROR,);
|
||||
|
||||
/* Remove Flow from PCC Rule */
|
||||
for (i = 0; i < pcc_rule->num_of_flow; i++)
|
||||
{
|
||||
FLOW_FREE(&pcc_rule->flow[i]);
|
||||
}
|
||||
pcc_rule->num_of_flow = 0;
|
||||
|
||||
for (i = 0; i < media_component->num_of_sub; i++)
|
||||
{
|
||||
rx_media_sub_component_t *sub = &media_component->sub[i];
|
||||
|
||||
if (sub->flow_number == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Copy Flow to PCC Rule */
|
||||
for (j = 0; j < sub->num_of_flow; j++)
|
||||
{
|
||||
flow_t *rx_flow = &sub->flow[j];
|
||||
flow_t *gx_flow = &pcc_rule->flow[pcc_rule->num_of_flow];
|
||||
|
||||
rv = flow_rx_to_gx(rx_flow, gx_flow);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("flow reformatting error");
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
pcc_rule->num_of_flow++;
|
||||
}
|
||||
}
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
||||
static status_t update_qos(
|
||||
pcc_rule_t *pcc_rule, rx_media_component_t *media_component)
|
||||
{
|
||||
status_t rv;
|
||||
int i, j;
|
||||
|
||||
d_assert(pcc_rule, return CORE_ERROR,);
|
||||
d_assert(media_component, return CORE_ERROR,);
|
||||
|
||||
pcc_rule->qos.mbr.downlink = 0;
|
||||
pcc_rule->qos.mbr.uplink = 0;
|
||||
pcc_rule->qos.gbr.downlink = 0;
|
||||
pcc_rule->qos.gbr.uplink = 0;
|
||||
|
||||
for (i = 0; i < media_component->num_of_sub; i++)
|
||||
{
|
||||
rx_media_sub_component_t *sub = &media_component->sub[i];
|
||||
|
||||
if (sub->flow_number == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < sub->num_of_flow; j++)
|
||||
{
|
||||
flow_t gx_flow;
|
||||
flow_t *rx_flow = &sub->flow[j];
|
||||
|
||||
rv = flow_rx_to_gx(rx_flow, &gx_flow);
|
||||
if (rv != CORE_OK)
|
||||
{
|
||||
d_error("flow reformatting error");
|
||||
return CORE_ERROR;
|
||||
}
|
||||
|
||||
if (gx_flow.direction == FLOW_DOWNLINK_ONLY)
|
||||
{
|
||||
if (sub->flow_usage == RX_FLOW_USAGE_RTCP)
|
||||
{
|
||||
if (media_component->rr_bandwidth &&
|
||||
media_component->rs_bandwidth)
|
||||
{
|
||||
pcc_rule->qos.mbr.downlink +=
|
||||
(media_component->rr_bandwidth +
|
||||
media_component->rs_bandwidth);
|
||||
}
|
||||
else if (media_component->max_requested_bandwidth_dl)
|
||||
{
|
||||
if (media_component->rr_bandwidth &&
|
||||
!media_component->rs_bandwidth)
|
||||
{
|
||||
pcc_rule->qos.mbr.downlink +=
|
||||
c_max(0.05 *
|
||||
media_component->max_requested_bandwidth_dl,
|
||||
media_component->rr_bandwidth);
|
||||
}
|
||||
if (!media_component->rr_bandwidth &&
|
||||
media_component->rs_bandwidth)
|
||||
{
|
||||
pcc_rule->qos.mbr.downlink +=
|
||||
c_max(0.05 *
|
||||
media_component->max_requested_bandwidth_dl,
|
||||
media_component->rs_bandwidth);
|
||||
}
|
||||
if (!media_component->rr_bandwidth &&
|
||||
!media_component->rs_bandwidth)
|
||||
{
|
||||
pcc_rule->qos.mbr.downlink +=
|
||||
0.05 *
|
||||
media_component->max_requested_bandwidth_dl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gx_flow.description)
|
||||
{
|
||||
pcc_rule->qos.mbr.downlink +=
|
||||
media_component->max_requested_bandwidth_dl;
|
||||
pcc_rule->qos.gbr.downlink +=
|
||||
media_component->min_requested_bandwidth_dl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (gx_flow.direction == FLOW_UPLINK_ONLY)
|
||||
{
|
||||
if (sub->flow_usage == RX_FLOW_USAGE_RTCP)
|
||||
{
|
||||
if (media_component->rr_bandwidth &&
|
||||
media_component->rs_bandwidth)
|
||||
{
|
||||
pcc_rule->qos.mbr.uplink +=
|
||||
(media_component->rr_bandwidth +
|
||||
media_component->rs_bandwidth);
|
||||
}
|
||||
else if (media_component->max_requested_bandwidth_ul)
|
||||
{
|
||||
if (media_component->rr_bandwidth &&
|
||||
!media_component->rs_bandwidth)
|
||||
{
|
||||
pcc_rule->qos.mbr.uplink +=
|
||||
c_max(0.05 *
|
||||
media_component->max_requested_bandwidth_ul,
|
||||
media_component->rr_bandwidth);
|
||||
}
|
||||
if (!media_component->rr_bandwidth &&
|
||||
media_component->rs_bandwidth)
|
||||
{
|
||||
pcc_rule->qos.mbr.uplink +=
|
||||
c_max(0.05 *
|
||||
media_component->max_requested_bandwidth_ul,
|
||||
media_component->rs_bandwidth);
|
||||
}
|
||||
if (!media_component->rr_bandwidth &&
|
||||
!media_component->rs_bandwidth)
|
||||
{
|
||||
pcc_rule->qos.mbr.uplink +=
|
||||
0.05 *
|
||||
media_component->max_requested_bandwidth_ul;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gx_flow.description)
|
||||
{
|
||||
pcc_rule->qos.mbr.uplink +=
|
||||
media_component->max_requested_bandwidth_ul;
|
||||
pcc_rule->qos.gbr.uplink +=
|
||||
media_component->min_requested_bandwidth_ul;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
d_assert(0, return CORE_ERROR,
|
||||
"Invalid Direction(%d)", gx_flow.direction);
|
||||
|
||||
FLOW_FREE(&gx_flow);
|
||||
}
|
||||
}
|
||||
|
||||
if (pcc_rule->qos.mbr.downlink == 0)
|
||||
{
|
||||
pcc_rule->qos.mbr.downlink +=
|
||||
media_component->max_requested_bandwidth_dl;
|
||||
pcc_rule->qos.mbr.downlink +=
|
||||
(media_component->rr_bandwidth + media_component->rs_bandwidth);
|
||||
}
|
||||
|
||||
if (pcc_rule->qos.mbr.uplink == 0)
|
||||
{
|
||||
pcc_rule->qos.mbr.uplink +=
|
||||
media_component->max_requested_bandwidth_ul;
|
||||
pcc_rule->qos.mbr.uplink +=
|
||||
(media_component->rr_bandwidth + media_component->rs_bandwidth);
|
||||
}
|
||||
|
||||
if (pcc_rule->qos.gbr.downlink == 0)
|
||||
pcc_rule->qos.gbr.downlink = pcc_rule->qos.mbr.downlink;
|
||||
if (pcc_rule->qos.gbr.uplink == 0)
|
||||
pcc_rule->qos.gbr.uplink = pcc_rule->qos.mbr.uplink;
|
||||
|
||||
return CORE_OK;
|
||||
}
|
||||
|
|
|
@ -87,6 +87,8 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp,
|
|||
char buf[CORE_ADDRSTRLEN];
|
||||
os0_t gx_sid = NULL;
|
||||
c_uint32_t result_code = RX_DIAMETER_IP_CAN_SESSION_NOT_AVAILABLE;
|
||||
|
||||
d_trace(3, "[PCRF] AA-Request : PCRF <-- P-CSCF\n");
|
||||
|
||||
d_assert(msg, return EINVAL,);
|
||||
d_assert(sess, return EINVAL,);
|
||||
|
@ -233,22 +235,36 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp,
|
|||
}
|
||||
case RX_AVP_CODE_MAX_REQUESTED_BANDWIDTH_DL:
|
||||
{
|
||||
media_component->mbr.downlink = hdr->avp_value->i32;
|
||||
media_component->max_requested_bandwidth_dl =
|
||||
hdr->avp_value->i32;
|
||||
break;
|
||||
}
|
||||
case RX_AVP_CODE_MAX_REQUESTED_BANDWIDTH_UL:
|
||||
{
|
||||
media_component->mbr.uplink = hdr->avp_value->i32;
|
||||
media_component->max_requested_bandwidth_ul =
|
||||
hdr->avp_value->i32;
|
||||
break;
|
||||
}
|
||||
case RX_AVP_CODE_RR_BANDWIDTH:
|
||||
{
|
||||
media_component->rr_bandwidth = hdr->avp_value->i32;
|
||||
break;
|
||||
}
|
||||
case RX_AVP_CODE_RS_BANDWIDTH:
|
||||
{
|
||||
media_component->rs_bandwidth = hdr->avp_value->i32;
|
||||
break;
|
||||
}
|
||||
case RX_AVP_CODE_MIN_REQUESTED_BANDWIDTH_DL:
|
||||
{
|
||||
media_component->gbr.downlink = hdr->avp_value->i32;
|
||||
media_component->min_requested_bandwidth_dl =
|
||||
hdr->avp_value->i32;
|
||||
break;
|
||||
}
|
||||
case RX_AVP_CODE_MIN_REQUESTED_BANDWIDTH_UL:
|
||||
{
|
||||
media_component->gbr.uplink = hdr->avp_value->i32;
|
||||
media_component->min_requested_bandwidth_ul =
|
||||
hdr->avp_value->i32;
|
||||
break;
|
||||
}
|
||||
case RX_AVP_CODE_MEDIA_SUB_COMPONENT:
|
||||
|
@ -430,6 +446,8 @@ status_t pcrf_rx_send_asr(c_uint8_t *rx_sid, c_uint32_t abort_cause)
|
|||
|
||||
d_assert(rx_sid, return CORE_ERROR,);
|
||||
|
||||
d_trace(3, "[PCRF] Abort-Session-Request : PCRF --> P-CSCF\n");
|
||||
|
||||
/* Create the request */
|
||||
ret = fd_msg_new(rx_cmd_asr, MSGFL_ALLOC_ETEID, &req);
|
||||
d_assert(ret == 0, return CORE_ERROR,);
|
||||
|
@ -526,28 +544,19 @@ static void pcrf_rx_asa_cb(void *data, struct msg **msg)
|
|||
{
|
||||
int ret;
|
||||
|
||||
struct sess_state *sess_data = NULL;
|
||||
struct timespec ts;
|
||||
struct session *session;
|
||||
struct avp *avp, *avpch1;
|
||||
struct avp_hdr *hdr;
|
||||
unsigned long dur;
|
||||
int error = 0;
|
||||
int new;
|
||||
c_int32_t result_code = 0;
|
||||
|
||||
ret = clock_gettime(CLOCK_REALTIME, &ts);
|
||||
d_assert(ret == 0, return,);
|
||||
d_trace(3, "[PCRF] Abort-Session-Answer : PCRF <-- P-CSCF\n");
|
||||
|
||||
/* Search the session, retrieve its data */
|
||||
ret = fd_msg_sess_get(fd_g_config->cnf_dict, *msg, &session, &new);
|
||||
d_assert(ret == 0, return,);
|
||||
d_assert(new == 0, return, );
|
||||
|
||||
ret = fd_sess_state_retrieve(pcrf_rx_reg, session, &sess_data);
|
||||
d_assert(ret == 0, return,);
|
||||
d_assert(sess_data && (void *)sess_data == data, return, );
|
||||
|
||||
/* Value of Result Code */
|
||||
ret = fd_msg_search_avp(*msg, fd_result_code, &avp);
|
||||
d_assert(ret == 0, return,);
|
||||
|
@ -578,7 +587,6 @@ static void pcrf_rx_asa_cb(void *data, struct msg **msg)
|
|||
else
|
||||
{
|
||||
d_error("no Result-Code");
|
||||
error++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -595,7 +603,6 @@ static void pcrf_rx_asa_cb(void *data, struct msg **msg)
|
|||
else
|
||||
{
|
||||
d_error("no_Origin-Host ");
|
||||
error++;
|
||||
}
|
||||
|
||||
/* Value of Origin-Realm */
|
||||
|
@ -611,60 +618,13 @@ static void pcrf_rx_asa_cb(void *data, struct msg **msg)
|
|||
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;
|
||||
d_error("ERROR DIAMETER Result Code(%d)", result_code);
|
||||
}
|
||||
|
||||
out:
|
||||
/* Free the message */
|
||||
d_assert(pthread_mutex_lock(&fd_logger_self()->stats_lock) == 0,, );
|
||||
dur = ((ts.tv_sec - sess_data->ts.tv_sec) * 1000000) +
|
||||
((ts.tv_nsec - sess_data->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++;
|
||||
|
||||
d_assert(pthread_mutex_unlock(&fd_logger_self()->stats_lock) == 0,, );
|
||||
|
||||
/* Display how long it took */
|
||||
if (ts.tv_nsec > sess_data->ts.tv_nsec)
|
||||
d_trace(3, "in %d.%06ld sec\n",
|
||||
(int)(ts.tv_sec - sess_data->ts.tv_sec),
|
||||
(long)(ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
|
||||
else
|
||||
d_trace(3, "in %d.%06ld sec\n",
|
||||
(int)(ts.tv_sec + 1 - sess_data->ts.tv_sec),
|
||||
(long)(1000000000 + ts.tv_nsec - sess_data->ts.tv_nsec) / 1000);
|
||||
|
||||
ret = fd_sess_state_store(pcrf_rx_reg, session, &sess_data);
|
||||
d_assert(ret == 0, return,);
|
||||
d_assert(sess_data == NULL, return,);
|
||||
|
||||
ret = fd_msg_free(*msg);
|
||||
d_assert(ret == 0,,);
|
||||
*msg = NULL;
|
||||
|
@ -686,6 +646,8 @@ static int pcrf_rx_str_cb( struct msg **msg, struct avp *avp,
|
|||
rx_message_t rx_message;
|
||||
|
||||
c_uint32_t result_code = RX_DIAMETER_IP_CAN_SESSION_NOT_AVAILABLE;
|
||||
|
||||
d_trace(3, "[PCRF] Session-Termination-Request : PCRF <-- P-CSCF\n");
|
||||
|
||||
d_assert(msg, return EINVAL,);
|
||||
d_assert(sess, return EINVAL,);
|
||||
|
|
|
@ -154,10 +154,14 @@ static status_t bearer_binding(pgw_sess_t *sess, gx_message_t *gx_message)
|
|||
tft_presence = 1;
|
||||
}
|
||||
|
||||
if (bearer->qos.mbr.downlink != pcc_rule->qos.mbr.downlink ||
|
||||
bearer->qos.mbr.uplink != pcc_rule->qos.mbr.uplink ||
|
||||
bearer->qos.gbr.downlink != pcc_rule->qos.gbr.downlink ||
|
||||
bearer->qos.gbr.uplink != pcc_rule->qos.gbr.uplink)
|
||||
if ((pcc_rule->qos.mbr.downlink &&
|
||||
bearer->qos.mbr.downlink != pcc_rule->qos.mbr.downlink) ||
|
||||
(pcc_rule->qos.mbr.uplink &&
|
||||
bearer->qos.mbr.uplink != pcc_rule->qos.mbr.uplink) ||
|
||||
(pcc_rule->qos.gbr.downlink &&
|
||||
bearer->qos.gbr.downlink != pcc_rule->qos.gbr.downlink) ||
|
||||
(pcc_rule->qos.gbr.uplink &&
|
||||
bearer->qos.gbr.uplink != pcc_rule->qos.gbr.uplink))
|
||||
{
|
||||
/* Update QoS parameter */
|
||||
memcpy(&bearer->qos, &pcc_rule->qos, sizeof(qos_t));
|
||||
|
|
|
@ -64,7 +64,7 @@ static int pcscf_rx_fb_cb(struct msg **msg, struct avp *avp,
|
|||
}
|
||||
|
||||
void pcscf_rx_send_aar(c_uint8_t **rx_sid, const char *ip,
|
||||
int qos_presence, int flow_presence)
|
||||
int qos_type, int flow_presence)
|
||||
{
|
||||
status_t rv;
|
||||
int ret;
|
||||
|
@ -239,7 +239,7 @@ void pcscf_rx_send_aar(c_uint8_t **rx_sid, const char *ip,
|
|||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
|
||||
if (qos_presence)
|
||||
if (qos_type == 1)
|
||||
{
|
||||
ret = fd_msg_avp_new(rx_max_requested_bandwidth_dl, 0, &avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
|
@ -251,7 +251,57 @@ void pcscf_rx_send_aar(c_uint8_t **rx_sid, const char *ip,
|
|||
|
||||
ret = fd_msg_avp_new(rx_max_requested_bandwidth_ul, 0, &avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
val.i32 = 32000;
|
||||
val.i32 = 96000;
|
||||
ret = fd_msg_avp_setvalue (avpch1, &val);
|
||||
d_assert(ret == 0, return,);
|
||||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
|
||||
ret = fd_msg_avp_new(rx_rr_bandwidth, 0, &avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
val.i32 = 2400;
|
||||
ret = fd_msg_avp_setvalue (avpch1, &val);
|
||||
d_assert(ret == 0, return,);
|
||||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
|
||||
ret = fd_msg_avp_new(rx_rs_bandwidth, 0, &avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
val.i32 = 2400;
|
||||
ret = fd_msg_avp_setvalue (avpch1, &val);
|
||||
d_assert(ret == 0, return,);
|
||||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
}
|
||||
else if (qos_type == 2)
|
||||
{
|
||||
ret = fd_msg_avp_new(rx_max_requested_bandwidth_dl, 0, &avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
val.i32 = 96000;
|
||||
ret = fd_msg_avp_setvalue (avpch1, &val);
|
||||
d_assert(ret == 0, return,);
|
||||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
|
||||
ret = fd_msg_avp_new(rx_max_requested_bandwidth_ul, 0, &avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
val.i32 = 96000;
|
||||
ret = fd_msg_avp_setvalue (avpch1, &val);
|
||||
d_assert(ret == 0, return,);
|
||||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
|
||||
ret = fd_msg_avp_new(rx_min_requested_bandwidth_dl, 0, &avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
val.i32 = 88000;
|
||||
ret = fd_msg_avp_setvalue (avpch1, &val);
|
||||
d_assert(ret == 0, return,);
|
||||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
|
||||
ret = fd_msg_avp_new(rx_min_requested_bandwidth_ul, 0, &avpch1);
|
||||
d_assert(ret == 0, return,);
|
||||
val.i32 = 88000;
|
||||
ret = fd_msg_avp_setvalue (avpch1, &val);
|
||||
d_assert(ret == 0, return,);
|
||||
ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1);
|
||||
|
|
|
@ -11,7 +11,7 @@ CORE_DECLARE(status_t) pcscf_fd_init(void);
|
|||
CORE_DECLARE(void) pcscf_fd_final(void);
|
||||
|
||||
CORE_DECLARE(void) pcscf_rx_send_aar(c_uint8_t **rx_sid, const char *ip,
|
||||
int qos_presence, int flow_presence);
|
||||
int qos_type, int flow_presence);
|
||||
CORE_DECLARE(void) pcscf_rx_send_str(c_uint8_t *rx_sid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -1351,7 +1351,7 @@ status_t tests1ap_build_deactivate_bearer_accept(
|
|||
"0500000005c00000 0001000800030001 00001a000a0927a9 a1b2bd057200ce00"
|
||||
"6440080055f50100 19d0100043400600 55f5011022",
|
||||
"000d40370000"
|
||||
"0500000005c00000 0001000800030001 00001a000a09274c b2ebbd056200ce00"
|
||||
"0500000005c00000 0001000800030001 00001a000a09277d 7f1f80056200ce00"
|
||||
"6440080055f50100 19d0100043400600 55f5011022",
|
||||
|
||||
"",
|
||||
|
|
|
@ -237,7 +237,7 @@ static void volte_test1(abts_case *tc, void *data)
|
|||
core_sleep(time_from_msec(300));
|
||||
|
||||
/* Send AA-Request */
|
||||
pcscf_rx_send_aar(&rx_sid, "45.45.0.3", 0, 1);
|
||||
pcscf_rx_send_aar(&rx_sid, "45.45.0.3", 1, 1);
|
||||
|
||||
/* Receive E-RAB Setup Request +
|
||||
* Activate dedicated EPS bearer context request */
|
||||
|
@ -263,7 +263,7 @@ static void volte_test1(abts_case *tc, void *data)
|
|||
core_sleep(time_from_msec(300));
|
||||
|
||||
/* Send AA-Request without Flow */
|
||||
pcscf_rx_send_aar(&rx_sid, "45.45.0.3", 1, 0);
|
||||
pcscf_rx_send_aar(&rx_sid, "45.45.0.3", 2, 1);
|
||||
|
||||
/* Receive E-RAB Modify Request +
|
||||
* Modify EPS bearer context request */
|
||||
|
@ -609,8 +609,8 @@ static void volte_test2(abts_case *tc, void *data)
|
|||
/* Send AA-Request */
|
||||
pcscf_rx_send_aar(&rx_sid, "45.45.0.5", 0, 1);
|
||||
|
||||
/* Receive E-RAB Setup Request +
|
||||
* Activate dedicated EPS bearer context request */
|
||||
/* Receive downlink NAS transport +
|
||||
* Modify EPS bearer context request */
|
||||
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
|
||||
rv = tests1ap_enb_read(sock, recvbuf);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
@ -630,7 +630,6 @@ static void volte_test2(abts_case *tc, void *data)
|
|||
rv = tests1ap_enb_send(sock, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
#if 0
|
||||
/* Receive E-RAB Release Command +
|
||||
* Deactivate EPS bearer context request */
|
||||
recvbuf = pkbuf_alloc(0, MAX_SDU_LEN);
|
||||
|
@ -652,7 +651,6 @@ static void volte_test2(abts_case *tc, void *data)
|
|||
rv = tests1ap_enb_send(sock, sendbuf);
|
||||
ABTS_INT_EQUAL(tc, CORE_OK, rv);
|
||||
|
||||
#endif
|
||||
core_sleep(time_from_msec(300));
|
||||
|
||||
/********** Remove Subscriber in Database */
|
||||
|
|
Loading…
Reference in New Issue