diff --git a/lib/core/include/3gpp_types.h b/lib/core/include/3gpp_types.h index cc8bdab66..17360d2ba 100644 --- a/lib/core/include/3gpp_types.h +++ b/lib/core/include/3gpp_types.h @@ -210,10 +210,16 @@ typedef struct _flow_t { /********************************** * PCC Rule Structure */ typedef struct _pcc_rule_t { +#define PCC_RULE_TYPE_INSTALL 1 +#define PCC_RULE_TYPE_REMOVE 2 + c_uint8_t type; + #define MAX_PCC_RULE_NAME_LEN 256 c_int8_t *name; + flow_t flow[MAX_NUM_OF_FLOW]; int num_of_flow; + #define GX_FLOW_STATUS_ENABLED_UPLINK 0 #define GX_FLOW_STATUS_ENABLED_DOWNLINK 1 #define GX_FLOW_STATUS_ENABLED 2 diff --git a/lib/fd/gx/gx_dict.h b/lib/fd/gx/gx_dict.h index aa41d2066..7b0cb53f2 100644 --- a/lib/fd/gx/gx_dict.h +++ b/lib/fd/gx/gx_dict.h @@ -10,6 +10,13 @@ extern "C" { #define GX_APPLICATION_ID 16777238 +#define GX_AVP_CODE_RE_AUTH_REQUEST_TYPE (285) +#define GX_AVP_CODE_CC_REQUEST_NUMBER (415) +#define GX_AVP_CODE_CC_REQUEST_TYPE (416) +#define GX_AVP_CODE_DEFAULT_EPS_BEARER_QOS (1049) +#define GX_AVP_CODE_SUPPORTED_FEATURES (628) +#define GX_AVP_CODE_CHARGING_RULE_INSTALL (1001) +#define GX_AVP_CODE_CHARGING_RULE_REMOVE (1002) #define GX_AVP_CODE_CHARGING_RULE_DEFINITION (1003) #define GX_AVP_CODE_CHARGING_RULE_NAME (1005) #define GX_AVP_CODE_FLOW_INFORMATION (1058) diff --git a/src/pgw/pgw_context.c b/src/pgw/pgw_context.c index a594431ee..1c5a56c15 100644 --- a/src/pgw/pgw_context.c +++ b/src/pgw/pgw_context.c @@ -1244,6 +1244,25 @@ pgw_bearer_t* pgw_bearer_find_by_ebi(pgw_sess_t *sess, c_uint8_t ebi) return bearer; } +pgw_bearer_t* pgw_bearer_find_by_name(pgw_sess_t *sess, c_int8_t *name) +{ + pgw_bearer_t *bearer = NULL; + + d_assert(sess, return NULL, "Null param"); + d_assert(name, return NULL, "Null param"); + + bearer = pgw_bearer_first(sess); + while (bearer) + { + if (bearer->name && strcmp(bearer->name, name) == 0) + return bearer; + + bearer = pgw_bearer_next(bearer); + } + + return NULL; +} + pgw_bearer_t* pgw_bearer_find_by_qci_arp(pgw_sess_t *sess, c_uint8_t qci, c_uint8_t priority_level, diff --git a/src/pgw/pgw_context.h b/src/pgw/pgw_context.h index 139927060..4b2778d59 100644 --- a/src/pgw/pgw_context.h +++ b/src/pgw/pgw_context.h @@ -232,6 +232,8 @@ CORE_DECLARE(pgw_bearer_t*) pgw_bearer_find_by_pgw_s5u_teid( c_uint32_t pgw_s5u_teid); CORE_DECLARE(pgw_bearer_t*) pgw_bearer_find_by_ebi( pgw_sess_t *sess, c_uint8_t ebi); +CORE_DECLARE(pgw_bearer_t*) pgw_bearer_find_by_name( + pgw_sess_t *sess, c_int8_t *name); CORE_DECLARE(pgw_bearer_t*) pgw_bearer_find_by_qci_arp(pgw_sess_t *sess, c_uint8_t qci, c_uint8_t priority_level, diff --git a/src/pgw/pgw_fd_path.c b/src/pgw/pgw_fd_path.c index 1830f7f2d..10377b37a 100644 --- a/src/pgw/pgw_fd_path.c +++ b/src/pgw/pgw_fd_path.c @@ -554,39 +554,6 @@ static void pgw_gx_cca_cb(void *data, struct msg **msg) error++; } - ret = fd_msg_search_avp(*msg, gx_charging_rule_install, &avp); - d_assert(ret == 0, return,); - if (avp) - { - ret = fd_msg_browse(avp, MSG_BRW_FIRST_CHILD, &avpch1, NULL); - d_assert(ret == 0, return,); - while(avpch1) - { - ret = fd_msg_avp_hdr(avpch1, &hdr); - d_assert(ret == 0, return,); - switch(hdr->avp_code) - { - case GX_AVP_CODE_CHARGING_RULE_DEFINITION: - { - pcc_rule_t *pcc_rule = - &gx_message->pcc_rule[gx_message->num_of_pcc_rule]; - - rv = decode_pcc_rule_definition(pcc_rule, avpch1, &error); - d_assert(rv == CORE_OK, return,); - - gx_message->num_of_pcc_rule++; - break; - } - default: - { - d_error("Not supported(%d)", hdr->avp_code); - break; - } - } - fd_msg_browse(avpch1, MSG_BRW_NEXT, &avpch1, NULL); - } - } - ret = fd_msg_search_avp(*msg, gx_qos_information, &avp); d_assert(ret == 0, return,); if (avp) @@ -658,6 +625,72 @@ static void pgw_gx_cca_cb(void *data, struct msg **msg) } } + ret = fd_msg_browse(*msg, MSG_BRW_FIRST_CHILD, &avp, NULL); + d_assert(ret == 0, return,); + while(avp) + { + ret = fd_msg_avp_hdr(avp, &hdr); + d_assert(ret == 0, return,); + switch(hdr->avp_code) + { + case AC_SESSION_ID: + case AC_ORIGIN_HOST: + case AC_ORIGIN_REALM: + case AC_DESTINATION_REALM: + case AC_RESULT_CODE: + case AC_ROUTE_RECORD: + case AC_PROXY_INFO: + case AC_AUTH_APPLICATION_ID: + break; + case GX_AVP_CODE_CC_REQUEST_TYPE: + case GX_AVP_CODE_CC_REQUEST_NUMBER: + case GX_AVP_CODE_SUPPORTED_FEATURES: + break; + case GX_AVP_CODE_QOS_INFORMATION: + case GX_AVP_CODE_DEFAULT_EPS_BEARER_QOS: + break; + case GX_AVP_CODE_CHARGING_RULE_INSTALL: + { + ret = fd_msg_browse(avp, MSG_BRW_FIRST_CHILD, &avpch1, NULL); + d_assert(ret == 0, return,); + while(avpch1) + { + ret = fd_msg_avp_hdr(avpch1, &hdr); + d_assert(ret == 0, return,); + switch(hdr->avp_code) + { + case GX_AVP_CODE_CHARGING_RULE_DEFINITION: + { + pcc_rule_t *pcc_rule = &gx_message->pcc_rule + [gx_message->num_of_pcc_rule]; + + rv = decode_pcc_rule_definition( + pcc_rule, avpch1, &error); + d_assert(rv == CORE_OK, return,); + + pcc_rule->type = PCC_RULE_TYPE_INSTALL; + gx_message->num_of_pcc_rule++; + break; + } + default: + { + d_error("Not supported(%d)", hdr->avp_code); + break; + } + } + fd_msg_browse(avpch1, MSG_BRW_NEXT, &avpch1, NULL); + } + break; + } + default: + { + d_warn("Not supported(%d)", hdr->avp_code); + break; + } + } + fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL); + } + out: if (!error) { @@ -796,37 +829,65 @@ static int pgw_gx_rar_cb( struct msg **msg, struct avp *avp, sess = sess_data->sess; d_assert(sess, return EINVAL,); - ret = fd_msg_search_avp(qry, gx_charging_rule_install, &avp); + ret = fd_msg_browse(qry, MSG_BRW_FIRST_CHILD, &avp, NULL); d_assert(ret == 0, return EINVAL,); - if (avp) + while(avp) { - ret = fd_msg_browse(avp, MSG_BRW_FIRST_CHILD, &avpch1, NULL); + ret = fd_msg_avp_hdr(avp, &hdr); d_assert(ret == 0, return EINVAL,); - while(avpch1) + switch(hdr->avp_code) { - ret = fd_msg_avp_hdr(avpch1, &hdr); - d_assert(ret == 0, return EINVAL,); - switch(hdr->avp_code) + case AC_SESSION_ID: + case AC_ORIGIN_HOST: + case AC_ORIGIN_REALM: + case AC_DESTINATION_REALM: + case AC_DESTINATION_HOST: + case AC_ROUTE_RECORD: + case AC_PROXY_INFO: + case AC_AUTH_APPLICATION_ID: + break; + case GX_AVP_CODE_RE_AUTH_REQUEST_TYPE: + break; + case GX_AVP_CODE_CHARGING_RULE_INSTALL: { - case GX_AVP_CODE_CHARGING_RULE_DEFINITION: + ret = fd_msg_browse(avp, MSG_BRW_FIRST_CHILD, &avpch1, NULL); + d_assert(ret == 0, return EINVAL,); + while(avpch1) { - pcc_rule_t *pcc_rule = - &gx_message->pcc_rule[gx_message->num_of_pcc_rule]; + ret = fd_msg_avp_hdr(avpch1, &hdr); + d_assert(ret == 0, return EINVAL,); + switch(hdr->avp_code) + { + case GX_AVP_CODE_CHARGING_RULE_DEFINITION: + { + pcc_rule_t *pcc_rule = &gx_message->pcc_rule + [gx_message->num_of_pcc_rule]; - rv = decode_pcc_rule_definition(pcc_rule, avpch1, NULL); - d_assert(rv == CORE_OK, return EINVAL,); + rv = decode_pcc_rule_definition( + pcc_rule, avpch1, NULL); + d_assert(rv == CORE_OK, return EINVAL,); - gx_message->num_of_pcc_rule++; - break; - } - default: - { - d_error("Not supported(%d)", hdr->avp_code); - break; + pcc_rule->type = PCC_RULE_TYPE_INSTALL; + gx_message->num_of_pcc_rule++; + break; + } + default: + { + d_error("Not supported(%d)", hdr->avp_code); + break; + } + } + fd_msg_browse(avpch1, MSG_BRW_NEXT, &avpch1, NULL); } + break; + } + default: + { + d_warn("Not supported(%d)", hdr->avp_code); + break; } - fd_msg_browse(avpch1, MSG_BRW_NEXT, &avpch1, NULL); } + fd_msg_browse(avp, MSG_BRW_NEXT, &avp, NULL); } /* Send Gx Event to PGW State Machine */ diff --git a/src/pgw/pgw_gx_handler.c b/src/pgw/pgw_gx_handler.c index 0d0ad9b5a..8c39c5ed1 100644 --- a/src/pgw/pgw_gx_handler.c +++ b/src/pgw/pgw_gx_handler.c @@ -99,59 +99,97 @@ static status_t bearer_binding(pgw_sess_t *sess, gx_message_t *gx_message) gtp_xact_t *xact = NULL; gtp_header_t h; pkbuf_t *pkbuf = NULL; + pgw_bearer_t *bearer = NULL; pcc_rule_t *pcc_rule = &gx_message->pcc_rule[i]; - pgw_bearer_t *bearer = pgw_bearer_find_by_qci_arp(sess, - pcc_rule->qos.qci, - pcc_rule->qos.arp.priority_level, - pcc_rule->qos.arp.pre_emption_capability, - pcc_rule->qos.arp.pre_emption_vulnerability); - if (bearer) + + d_assert(pcc_rule, return CORE_ERROR,); + if (pcc_rule->name == NULL) { - d_error("CHECK WEBUI : PCC Rule Modification is NOT implemented"); - d_error("Please remove Flow in PCC Rule"); + d_error("No PCC Rule Name"); + continue; + } + + if (pcc_rule->type == PCC_RULE_TYPE_INSTALL) + { + bearer = pgw_bearer_find_by_qci_arp(sess, + pcc_rule->qos.qci, + pcc_rule->qos.arp.priority_level, + pcc_rule->qos.arp.pre_emption_capability, + pcc_rule->qos.arp.pre_emption_vulnerability); + if (bearer) + { + d_error("CHECK WEBUI : " + "PCC Rule Modification is NOT implemented"); + d_error("Please remove Flow in PCC Rule " + "[QCI:%d, ARP:%d,%d,%d]", + pcc_rule->qos.qci, + pcc_rule->qos.arp.priority_level, + pcc_rule->qos.arp.pre_emption_capability, + pcc_rule->qos.arp.pre_emption_vulnerability); + + return CORE_ERROR; + } + + bearer = pgw_bearer_find_by_name(sess, pcc_rule->name); + if (bearer) + { + d_error("CHECK WEBUI : " + "PCC Rule Modification is NOT implemented"); + d_error("Please remove Flow in PCC Rule [Name:%d]", + pcc_rule->name); + + return CORE_ERROR; + } + + bearer = pgw_bearer_add(sess); + d_assert(bearer, return CORE_ERROR, "Null param"); + + bearer->name = core_strdup(pcc_rule->name); + d_assert(bearer->name, return CORE_ERROR,); + + memcpy(&bearer->qos, &pcc_rule->qos, sizeof(qos_t)); + + for (j = 0; j < pcc_rule->num_of_flow; j++) + { + flow_t *flow = &pcc_rule->flow[j]; + pgw_rule_t rule; + pgw_pf_t *pf = NULL; + + d_assert(flow, return CORE_ERROR, "Null param"); + d_assert(flow->description, return CORE_ERROR, "Null param"); + + rv = pgw_compile_packet_filter(&rule, flow->description); + d_assert(rv == CORE_OK, return CORE_ERROR, + "Failed to compile packet filter"); + + pf = pgw_pf_add(bearer, pcc_rule->precedence); + d_assert(pf, return CORE_ERROR, "Null param"); + + memcpy(&pf->rule, &rule, sizeof(pgw_rule_t)); + pf->direction = flow->direction; + } + + memset(&h, 0, sizeof(gtp_header_t)); + h.type = GTP_CREATE_BEARER_REQUEST_TYPE; + h.teid = sess->sgw_s5c_teid; + + rv = pgw_s5c_build_create_bearer_request(&pkbuf, h.type, bearer); + d_assert(rv == CORE_OK, return CORE_ERROR, "S11 build error"); + + xact = gtp_xact_local_create(sess->gnode, &h, pkbuf); + d_assert(xact, return CORE_ERROR, "Null param"); + + rv = gtp_xact_commit(xact); + d_assert(rv == CORE_OK, return CORE_ERROR, "xact_commit error"); + } + else if (pcc_rule->type == PCC_RULE_TYPE_REMOVE) + { + d_warn("Not implmeneted"); return CORE_ERROR; } - - bearer = pgw_bearer_add(sess); - d_assert(bearer, return CORE_ERROR, "Null param"); - - bearer->name = core_strdup(pcc_rule->name); - d_assert(bearer->name, return CORE_ERROR,); - - memcpy(&bearer->qos, &pcc_rule->qos, sizeof(qos_t)); - - for (j = 0; j < pcc_rule->num_of_flow; j++) - { - flow_t *flow = &pcc_rule->flow[j]; - pgw_rule_t rule; - pgw_pf_t *pf = NULL; - - d_assert(flow, return CORE_ERROR, "Null param"); - d_assert(flow->description, return CORE_ERROR, "Null param"); - - rv = pgw_compile_packet_filter(&rule, flow->description); - d_assert(rv == CORE_OK, return CORE_ERROR, "Failed to compile packet filter"); - - pf = pgw_pf_add(bearer, pcc_rule->precedence); - d_assert(pf, return CORE_ERROR, "Null param"); - - memcpy(&pf->rule, &rule, sizeof(pgw_rule_t)); - pf->direction = flow->direction; - } - - memset(&h, 0, sizeof(gtp_header_t)); - h.type = GTP_CREATE_BEARER_REQUEST_TYPE; - h.teid = sess->sgw_s5c_teid; - - rv = pgw_s5c_build_create_bearer_request(&pkbuf, h.type, bearer); - d_assert(rv == CORE_OK, return CORE_ERROR, "S11 build error"); - - xact = gtp_xact_local_create(sess->gnode, &h, pkbuf); - d_assert(xact, return CORE_ERROR, "Null param"); - - rv = gtp_xact_commit(xact); - d_assert(rv == CORE_OK, return CORE_ERROR, "xact_commit error"); + else + d_assert(0, return CORE_ERROR, "Invalid type(%d)", pcc_rule->type); } return CORE_OK;