From f577f8dc9fe9d1d3d792e46a25908dd612400bda Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 29 Dec 2019 12:36:59 +0900 Subject: [PATCH] Whether to include TFT in Update Bearer Request (#336) If Rx media component flow is not changed, Exclude TFT info in the GTP Update Bearer Request --- src/pcrf/pcrf-gx-path.c | 10 +-- src/pgw/pgw-gx-handler.c | 125 +++++++++++++++++++++++++++++++++--- src/pgw/pgw-s5c-build.c | 131 +++----------------------------------- src/pgw/pgw-s5c-build.h | 4 +- src/pgw/pgw-s5c-handler.c | 2 +- 5 files changed, 135 insertions(+), 137 deletions(-) diff --git a/src/pcrf/pcrf-gx-path.c b/src/pcrf/pcrf-gx-path.c index 04e1e0a3c..717843e64 100644 --- a/src/pcrf/pcrf-gx-path.c +++ b/src/pcrf/pcrf-gx-path.c @@ -763,7 +763,8 @@ int pcrf_gx_send_rar( flow_presence = 1; rv = install_flow(pcc_rule, media_component); if (rv != OGS_OK) { - rx_message->result_code = OGS_DIAM_RX_DIAMETER_FILTER_RESTRICTIONS; + rx_message->result_code = + OGS_DIAM_RX_DIAMETER_FILTER_RESTRICTIONS; ogs_error("install_flow() failed"); goto out; } @@ -775,7 +776,8 @@ int pcrf_gx_send_rar( /* Check Flow */ count = matched_flow(pcc_rule, media_component); if (count == -1) { - rx_message->result_code = OGS_DIAM_RX_DIAMETER_FILTER_RESTRICTIONS; + rx_message->result_code = + OGS_DIAM_RX_DIAMETER_FILTER_RESTRICTIONS; ogs_error("matched_flow() failed"); goto out; } @@ -1321,8 +1323,8 @@ static int flow_rx_to_gx(ogs_flow_t *rx_flow, ogs_flow_t *gx_flow) return OGS_OK; } -static int matched_flow( - ogs_pcc_rule_t *pcc_rule, ogs_diam_rx_media_component_t *media_component) +static int matched_flow(ogs_pcc_rule_t *pcc_rule, + ogs_diam_rx_media_component_t *media_component) { int rv; int i, j, k; diff --git a/src/pgw/pgw-gx-handler.c b/src/pgw/pgw-gx-handler.c index fb3566aa9..904df6a33 100644 --- a/src/pgw/pgw-gx-handler.c +++ b/src/pgw/pgw-gx-handler.c @@ -23,6 +23,10 @@ #include "pgw-gx-handler.h" #include "pgw-ipfw.h" +#include "ipfw/ipfw2.h" + +static void encode_traffic_flow_template( + ogs_gtp_tft_t *tft, pgw_bearer_t *bearer); static void bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message); static void timeout(ogs_gtp_xact_t *xact, void *data) @@ -114,6 +118,109 @@ void pgw_gx_handle_re_auth_request( bearer_binding(sess, gx_message); } +static void encode_traffic_flow_template( + ogs_gtp_tft_t *tft, pgw_bearer_t *bearer) +{ + int i, j, len; + pgw_pf_t *pf = NULL; + + ogs_assert(tft); + ogs_assert(bearer); + + memset(tft, 0, sizeof(*tft)); + tft->code = OGS_GTP_TFT_CODE_CREATE_NEW_TFT; + + i = 0; + pf = pgw_pf_first(bearer); + while (pf) { + tft->pf[i].direction = pf->direction; + tft->pf[i].identifier = pf->identifier - 1; + tft->pf[i].precedence = i+1; + + j = 0, len = 0; + if (pf->rule.proto) { + tft->pf[i].component[j].type = + GTP_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE; + tft->pf[i].component[j].proto = pf->rule.proto; + j++; len += 2; + } + + if (pf->rule.ipv4_local) { + tft->pf[i].component[j].type = + GTP_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE; + tft->pf[i].component[j].ipv4.addr = pf->rule.ip.local.addr[0]; + tft->pf[i].component[j].ipv4.mask = pf->rule.ip.local.mask[0]; + j++; len += 9; + } + + if (pf->rule.ipv4_remote) { + tft->pf[i].component[j].type = + GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE; + tft->pf[i].component[j].ipv4.addr = pf->rule.ip.remote.addr[0]; + tft->pf[i].component[j].ipv4.mask = pf->rule.ip.remote.mask[0]; + j++; len += 9; + } + + if (pf->rule.ipv6_local) { + tft->pf[i].component[j].type = + GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE; + memcpy(tft->pf[i].component[j].ipv6.addr, pf->rule.ip.local.addr, + sizeof pf->rule.ip.local.addr); + tft->pf[i].component[j].ipv6.prefixlen = + contigmask((uint8_t *)pf->rule.ip.local.mask, 128); + j++; len += 18; + } + + if (pf->rule.ipv6_remote) { + tft->pf[i].component[j].type = + GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE; + memcpy(tft->pf[i].component[j].ipv6.addr, pf->rule.ip.remote.addr, + sizeof pf->rule.ip.remote.addr); + tft->pf[i].component[j].ipv6.prefixlen = + contigmask((uint8_t *)pf->rule.ip.remote.mask, 128); + j++; len += 18; + } + + if (pf->rule.port.local.low) { + if (pf->rule.port.local.low == pf->rule.port.local.high) + { + tft->pf[i].component[j].type = + GTP_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE; + tft->pf[i].component[j].port.low = pf->rule.port.local.low; + j++; len += 3; + } else { + tft->pf[i].component[j].type = + GTP_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE; + tft->pf[i].component[j].port.low = pf->rule.port.local.low; + tft->pf[i].component[j].port.high = pf->rule.port.local.high; + j++; len += 5; + } + } + + if (pf->rule.port.remote.low) { + if (pf->rule.port.remote.low == pf->rule.port.remote.high) { + tft->pf[i].component[j].type = + GTP_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE; + tft->pf[i].component[j].port.low = pf->rule.port.remote.low; + j++; len += 3; + } else { + tft->pf[i].component[j].type = + GTP_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE; + tft->pf[i].component[j].port.low = pf->rule.port.remote.low; + tft->pf[i].component[j].port.high = pf->rule.port.remote.high; + j++; len += 5; + } + } + + tft->pf[i].num_of_component = j; + tft->pf[i].length = len; + i++; + + pf = pgw_pf_next(pf); + } + tft->num_of_packet_filter = i; +} + static void bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message) { int rv; @@ -131,7 +238,7 @@ static void bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message) ogs_pcc_rule_t *pcc_rule = &gx_message->pcc_rule[i]; int bearer_created = 0; int qos_presence = 0; - int tft_presence = 0; + ogs_gtp_tft_t tft; ogs_assert(pcc_rule); if (pcc_rule->name == NULL) { @@ -162,9 +269,6 @@ static void bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message) if (pcc_rule->num_of_flow) { /* Remove all previous flow */ pgw_pf_remove_all(bearer); - - /* Update Bearer Request will encode updated TFT */ - tft_presence = 1; } if ((pcc_rule->qos.mbr.downlink && @@ -182,9 +286,9 @@ static void bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message) qos_presence = 1; } - if (tft_presence == 0 && qos_presence == 0) { + if (pcc_rule->num_of_flow == 0 && qos_presence == 0) { ogs_warn("[IGNORE] Update Bearer Request : " - "Both QoS and TFT is NULL"); + "Both QoS and TFT are NULL"); continue; } } @@ -206,14 +310,17 @@ static void bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message) memcpy(&pf->rule, &rule, sizeof(pgw_rule_t)); pf->direction = flow->direction; } + memset(&tft, 0, sizeof tft); + if (pcc_rule->num_of_flow) + encode_traffic_flow_template(&tft, bearer); memset(&h, 0, sizeof(ogs_gtp_header_t)); - if (bearer_created == 1) { h.type = OGS_GTP_CREATE_BEARER_REQUEST_TYPE; h.teid = sess->sgw_s5c_teid; - pkbuf = pgw_s5c_build_create_bearer_request(h.type, bearer); + pkbuf = pgw_s5c_build_create_bearer_request( + h.type, bearer, pcc_rule->num_of_flow ? &tft : NULL); ogs_expect_or_return(pkbuf); } else { h.type = OGS_GTP_UPDATE_BEARER_REQUEST_TYPE; @@ -222,7 +329,7 @@ static void bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message) pkbuf = pgw_s5c_build_update_bearer_request( h.type, bearer, OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, - tft_presence, NULL, qos_presence); + pcc_rule->num_of_flow ? &tft : NULL, qos_presence); ogs_expect_or_return(pkbuf); } diff --git a/src/pgw/pgw-s5c-build.c b/src/pgw/pgw-s5c-build.c index c7a32f4d7..2e50a1eb7 100644 --- a/src/pgw/pgw-s5c-build.c +++ b/src/pgw/pgw-s5c-build.c @@ -177,111 +177,8 @@ ogs_pkbuf_t *pgw_s5c_build_delete_session_response( return ogs_gtp_build_msg(>p_message); } -static void encode_traffic_flow_template( - ogs_gtp_tft_t *tft, pgw_bearer_t *bearer) -{ - int i, j, len; - pgw_pf_t *pf = NULL; - - ogs_assert(tft); - ogs_assert(bearer); - - memset(tft, 0, sizeof(*tft)); - tft->code = OGS_GTP_TFT_CODE_CREATE_NEW_TFT; - - i = 0; - pf = pgw_pf_first(bearer); - while (pf) { - tft->pf[i].direction = pf->direction; - tft->pf[i].identifier = pf->identifier - 1; - tft->pf[i].precedence = i+1; - - j = 0, len = 0; - if (pf->rule.proto) { - tft->pf[i].component[j].type = - GTP_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE; - tft->pf[i].component[j].proto = pf->rule.proto; - j++; len += 2; - } - - if (pf->rule.ipv4_local) { - tft->pf[i].component[j].type = - GTP_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE; - tft->pf[i].component[j].ipv4.addr = pf->rule.ip.local.addr[0]; - tft->pf[i].component[j].ipv4.mask = pf->rule.ip.local.mask[0]; - j++; len += 9; - } - - if (pf->rule.ipv4_remote) { - tft->pf[i].component[j].type = - GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE; - tft->pf[i].component[j].ipv4.addr = pf->rule.ip.remote.addr[0]; - tft->pf[i].component[j].ipv4.mask = pf->rule.ip.remote.mask[0]; - j++; len += 9; - } - - if (pf->rule.ipv6_local) { - tft->pf[i].component[j].type = - GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE; - memcpy(tft->pf[i].component[j].ipv6.addr, pf->rule.ip.local.addr, - sizeof pf->rule.ip.local.addr); - tft->pf[i].component[j].ipv6.prefixlen = - contigmask((uint8_t *)pf->rule.ip.local.mask, 128); - j++; len += 18; - } - - if (pf->rule.ipv6_remote) { - tft->pf[i].component[j].type = - GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE; - memcpy(tft->pf[i].component[j].ipv6.addr, pf->rule.ip.remote.addr, - sizeof pf->rule.ip.remote.addr); - tft->pf[i].component[j].ipv6.prefixlen = - contigmask((uint8_t *)pf->rule.ip.remote.mask, 128); - j++; len += 18; - } - - if (pf->rule.port.local.low) { - if (pf->rule.port.local.low == pf->rule.port.local.high) - { - tft->pf[i].component[j].type = - GTP_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE; - tft->pf[i].component[j].port.low = pf->rule.port.local.low; - j++; len += 3; - } else { - tft->pf[i].component[j].type = - GTP_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE; - tft->pf[i].component[j].port.low = pf->rule.port.local.low; - tft->pf[i].component[j].port.high = pf->rule.port.local.high; - j++; len += 5; - } - } - - if (pf->rule.port.remote.low) { - if (pf->rule.port.remote.low == pf->rule.port.remote.high) { - tft->pf[i].component[j].type = - GTP_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE; - tft->pf[i].component[j].port.low = pf->rule.port.remote.low; - j++; len += 3; - } else { - tft->pf[i].component[j].type = - GTP_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE; - tft->pf[i].component[j].port.low = pf->rule.port.remote.low; - tft->pf[i].component[j].port.high = pf->rule.port.remote.high; - j++; len += 5; - } - } - - tft->pf[i].num_of_component = j; - tft->pf[i].length = len; - i++; - - pf = pgw_pf_next(pf); - } - tft->num_of_packet_filter = i; -} - ogs_pkbuf_t *pgw_s5c_build_create_bearer_request( - uint8_t type, pgw_bearer_t *bearer) + uint8_t type, pgw_bearer_t *bearer, ogs_gtp_tft_t *tft) { int rv; pgw_sess_t *sess = NULL; @@ -293,7 +190,6 @@ ogs_pkbuf_t *pgw_s5c_build_create_bearer_request( ogs_gtp_f_teid_t pgw_s5u_teid; ogs_gtp_bearer_qos_t bearer_qos; char bearer_qos_buf[GTP_BEARER_QOS_LEN]; - ogs_gtp_tft_t tft; int len; char tft_buf[OGS_GTP_MAX_TRAFFIC_FLOW_TEMPLATE]; @@ -348,10 +244,11 @@ ogs_pkbuf_t *pgw_s5c_build_create_bearer_request( &bearer_qos, bearer_qos_buf, GTP_BEARER_QOS_LEN); /* Bearer TFT */ - encode_traffic_flow_template(&tft, bearer); - req->bearer_contexts.tft.presence = 1; - ogs_gtp_build_tft(&req->bearer_contexts.tft, - &tft, tft_buf, OGS_GTP_MAX_TRAFFIC_FLOW_TEMPLATE); + if (tft && tft->num_of_packet_filter) { + req->bearer_contexts.tft.presence = 1; + ogs_gtp_build_tft(&req->bearer_contexts.tft, + tft, tft_buf, OGS_GTP_MAX_TRAFFIC_FLOW_TEMPLATE); + } gtp_message.h.type = type; return ogs_gtp_build_msg(>p_message); @@ -359,7 +256,7 @@ ogs_pkbuf_t *pgw_s5c_build_create_bearer_request( ogs_pkbuf_t *pgw_s5c_build_update_bearer_request( uint8_t type, pgw_bearer_t *bearer, uint8_t pti, - int tft_presence, ogs_gtp_tft_t *new_tft, int qos_presence) + ogs_gtp_tft_t *tft, int qos_presence) { pgw_sess_t *sess = NULL; @@ -369,7 +266,6 @@ ogs_pkbuf_t *pgw_s5c_build_update_bearer_request( ogs_gtp_ambr_t ambr; ogs_gtp_bearer_qos_t bearer_qos; char bearer_qos_buf[GTP_BEARER_QOS_LEN]; - ogs_gtp_tft_t tft; char tft_buf[OGS_GTP_MAX_TRAFFIC_FLOW_TEMPLATE]; ogs_assert(bearer); @@ -429,17 +325,10 @@ ogs_pkbuf_t *pgw_s5c_build_update_bearer_request( } /* Bearer TFT */ - if (tft_presence == 1) { - if (new_tft) { - ogs_gtp_build_tft(&req->bearer_contexts.tft, - new_tft, tft_buf, OGS_GTP_MAX_TRAFFIC_FLOW_TEMPLATE); - } else { - encode_traffic_flow_template(&tft, bearer); - ogs_gtp_build_tft(&req->bearer_contexts.tft, - &tft, tft_buf, OGS_GTP_MAX_TRAFFIC_FLOW_TEMPLATE); - } - + if (tft && tft->num_of_packet_filter) { req->bearer_contexts.tft.presence = 1; + ogs_gtp_build_tft(&req->bearer_contexts.tft, + tft, tft_buf, OGS_GTP_MAX_TRAFFIC_FLOW_TEMPLATE); } gtp_message.h.type = type; diff --git a/src/pgw/pgw-s5c-build.h b/src/pgw/pgw-s5c-build.h index 377b8c0ec..d5f341872 100644 --- a/src/pgw/pgw-s5c-build.h +++ b/src/pgw/pgw-s5c-build.h @@ -35,10 +35,10 @@ ogs_pkbuf_t *pgw_s5c_build_delete_session_response( ogs_gtp_delete_session_request_t *req); ogs_pkbuf_t *pgw_s5c_build_create_bearer_request( - uint8_t type, pgw_bearer_t *bearer); + uint8_t type, pgw_bearer_t *bearer, ogs_gtp_tft_t *tft); ogs_pkbuf_t *pgw_s5c_build_update_bearer_request( uint8_t type, pgw_bearer_t *bearer, uint8_t pti, - int tft_presence, ogs_gtp_tft_t *new_tft, int qos_presence); + ogs_gtp_tft_t *tft, int qos_presence); ogs_pkbuf_t *pgw_s5c_build_delete_bearer_request( uint8_t type, pgw_bearer_t *bearer, uint8_t pti); #ifdef __cplusplus diff --git a/src/pgw/pgw-s5c-handler.c b/src/pgw/pgw-s5c-handler.c index e2e41688a..6921953d2 100644 --- a/src/pgw/pgw-s5c-handler.c +++ b/src/pgw/pgw-s5c-handler.c @@ -546,7 +546,7 @@ void pgw_s5c_handle_bearer_resource_command( pkbuf = pgw_s5c_build_update_bearer_request( h.type, bearer, cmd->procedure_transaction_id.u8, - tft_presence, &tft, qos_presence); + tft_presence ? &tft : NULL, qos_presence); ogs_expect_or_return(pkbuf); rv = ogs_gtp_xact_update_tx(xact, &h, pkbuf);