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
This commit is contained in:
Sukchan Lee
2019-12-29 12:36:59 +09:00
parent 4fcbb65eca
commit f577f8dc9f
5 changed files with 135 additions and 137 deletions

View File

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

View File

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

View File

@@ -177,111 +177,8 @@ ogs_pkbuf_t *pgw_s5c_build_delete_session_response(
return ogs_gtp_build_msg(&gtp_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(&gtp_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;

View File

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

View File

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