mirror of
https://github.com/open5gs/open5gs.git
synced 2025-11-02 04:53:37 +00:00
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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user