Add Bearer Resource Modification feature (#336)

This commit is contained in:
Sukchan Lee 2019-12-28 21:46:30 +09:00
parent e6432868de
commit d191a5135e
49 changed files with 2223 additions and 292 deletions

View File

@ -58,6 +58,8 @@ extern "C" {
#define OGS_TIME_TO_BCD(x) \
(((((x) % 10) << 4) & 0xf0) | (((x) / 10) & 0x0f))
#define OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED 0
/**********************************
* PLMN_ID Structure */
typedef struct ogs_plmn_id_s {

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by gtp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2019-12-05 15:41:02.700546 by acetcom
* Created on: 2019-12-23 11:28:04.952636 by acetcom
* from 29274-d80.docx
******************************************************************************/
@ -534,10 +534,10 @@ ogs_tlv_desc_t ogs_gtp_tlv_desc_pdn_type_0 =
ogs_tlv_desc_t ogs_gtp_tlv_desc_pti_0 =
{
OGS_TLV_VAR_STR,
OGS_TLV_UINT8,
"PTI",
OGS_GTP_PTI_TYPE,
0,
1,
0,
sizeof(ogs_gtp_tlv_pti_t),
{ NULL }
@ -2437,6 +2437,48 @@ ogs_tlv_desc_t ogs_gtp_tlv_desc_delete_bearer_failure_indication =
NULL,
}};
ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_resource_command =
{
OGS_TLV_MESSAGE,
"Bearer Resource Command",
0, 0, 0, 0, {
&ogs_gtp_tlv_desc_ebi_0,
&ogs_gtp_tlv_desc_pti_0,
&ogs_gtp_tlv_desc_flow_qos_0,
&ogs_gtp_tlv_desc_tad_0,
&ogs_gtp_tlv_desc_rat_type_0,
&ogs_gtp_tlv_desc_serving_network_0,
&ogs_gtp_tlv_desc_uli_0,
&ogs_gtp_tlv_desc_ebi_1,
&ogs_gtp_tlv_desc_indication_0,
&ogs_gtp_tlv_desc_f_teid_0,
&ogs_gtp_tlv_desc_f_teid_1,
&ogs_gtp_tlv_desc_pco_0,
&ogs_gtp_tlv_desc_signalling_priority_indication_0,
&ogs_gtp_tlv_desc_overload_control_information_0,
&ogs_gtp_tlv_desc_overload_control_information_1,
&ogs_gtp_tlv_desc_f_container_0,
&ogs_gtp_tlv_desc_epco_0,
&ogs_gtp_tlv_desc_f_teid_2,
NULL,
}};
ogs_tlv_desc_t ogs_gtp_tlv_desc_bearer_resource_failure_indication =
{
OGS_TLV_MESSAGE,
"Bearer Resource Failure Indication",
0, 0, 0, 0, {
&ogs_gtp_tlv_desc_cause_0,
&ogs_gtp_tlv_desc_ebi_0,
&ogs_gtp_tlv_desc_pti_0,
&ogs_gtp_tlv_desc_indication_0,
&ogs_gtp_tlv_desc_overload_control_information_0,
&ogs_gtp_tlv_desc_overload_control_information_1,
&ogs_gtp_tlv_desc_recovery_0,
&ogs_gtp_tlv_desc_f_container_0,
NULL,
}};
ogs_tlv_desc_t ogs_gtp_tlv_desc_downlink_data_notification_failure_indication =
{
OGS_TLV_MESSAGE,
@ -2839,6 +2881,14 @@ int ogs_gtp_parse_msg(ogs_gtp_message_t *gtp_message, ogs_pkbuf_t *pkbuf)
rv = ogs_tlv_parse_msg(&gtp_message->delete_bearer_failure_indication,
&ogs_gtp_tlv_desc_delete_bearer_failure_indication, pkbuf, OGS_TLV_MODE_T1_L2_I1);
break;
case OGS_GTP_BEARER_RESOURCE_COMMAND_TYPE:
rv = ogs_tlv_parse_msg(&gtp_message->bearer_resource_command,
&ogs_gtp_tlv_desc_bearer_resource_command, pkbuf, OGS_TLV_MODE_T1_L2_I1);
break;
case OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE:
rv = ogs_tlv_parse_msg(&gtp_message->bearer_resource_failure_indication,
&ogs_gtp_tlv_desc_bearer_resource_failure_indication, pkbuf, OGS_TLV_MODE_T1_L2_I1);
break;
case OGS_GTP_DOWNLINK_DATA_NOTIFICATION_FAILURE_INDICATION_TYPE:
rv = ogs_tlv_parse_msg(&gtp_message->downlink_data_notification_failure_indication,
&ogs_gtp_tlv_desc_downlink_data_notification_failure_indication, pkbuf, OGS_TLV_MODE_T1_L2_I1);
@ -2969,6 +3019,14 @@ ogs_pkbuf_t *ogs_gtp_build_msg(ogs_gtp_message_t *gtp_message)
pkbuf = ogs_tlv_build_msg(&ogs_gtp_tlv_desc_delete_bearer_failure_indication,
&gtp_message->delete_bearer_failure_indication, OGS_TLV_MODE_T1_L2_I1);
break;
case OGS_GTP_BEARER_RESOURCE_COMMAND_TYPE:
pkbuf = ogs_tlv_build_msg(&ogs_gtp_tlv_desc_bearer_resource_command,
&gtp_message->bearer_resource_command, OGS_TLV_MODE_T1_L2_I1);
break;
case OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE:
pkbuf = ogs_tlv_build_msg(&ogs_gtp_tlv_desc_bearer_resource_failure_indication,
&gtp_message->bearer_resource_failure_indication, OGS_TLV_MODE_T1_L2_I1);
break;
case OGS_GTP_DOWNLINK_DATA_NOTIFICATION_FAILURE_INDICATION_TYPE:
pkbuf = ogs_tlv_build_msg(&ogs_gtp_tlv_desc_downlink_data_notification_failure_indication,
&gtp_message->downlink_data_notification_failure_indication, OGS_TLV_MODE_T1_L2_I1);

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by gtp-tlv.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2019-12-05 15:41:02.692263 by acetcom
* Created on: 2019-12-23 11:28:04.943360 by acetcom
* from 29274-d80.docx
******************************************************************************/
@ -505,7 +505,7 @@ typedef ogs_tlv_octet_t ogs_gtp_tlv_charging_characteristics_t;
typedef ogs_tlv_octet_t ogs_gtp_tlv_trace_information_t;
typedef ogs_tlv_octet_t ogs_gtp_tlv_bearer_flags_t;
typedef ogs_tlv_uint8_t ogs_gtp_tlv_pdn_type_t;
typedef ogs_tlv_octet_t ogs_gtp_tlv_pti_t;
typedef ogs_tlv_uint8_t ogs_gtp_tlv_pti_t;
typedef ogs_tlv_octet_t ogs_gtp_tlv_mm_context_t;
typedef ogs_tlv_octet_t ogs_gtp_tlv_pdu_numbers_t;
typedef ogs_tlv_octet_t ogs_gtp_tlv_p_tmsi_t;
@ -893,6 +893,38 @@ typedef struct ogs_gtp_delete_bearer_failure_indication_s {
ogs_gtp_tlv_overload_control_information_t sgw_s_overload_control_information;
} ogs_gtp_delete_bearer_failure_indication_t;
typedef struct ogs_gtp_bearer_resource_command_s {
ogs_gtp_tlv_ebi_t linked_eps_bearer_id;
ogs_gtp_tlv_pti_t procedure_transaction_id;
ogs_gtp_tlv_flow_qos_t flow_quality_of_service;
ogs_gtp_tlv_tad_t traffic_aggregate_description;
ogs_gtp_tlv_rat_type_t rat_type;
ogs_gtp_tlv_serving_network_t serving_network;
ogs_gtp_tlv_uli_t user_location_information;
ogs_gtp_tlv_ebi_t eps_bearer_id;
ogs_gtp_tlv_indication_t indication_flags;
ogs_gtp_tlv_f_teid_t s4_u_sgsn_f_teid;
ogs_gtp_tlv_f_teid_t s12_rnc_f_teid;
ogs_gtp_tlv_pco_t protocol_configuration_options;
ogs_gtp_tlv_signalling_priority_indication_t signalling_priority_indication__;
ogs_gtp_tlv_overload_control_information_t mme_s4_sgsn_s_overload_control_information;
ogs_gtp_tlv_overload_control_information_t sgw_s_overload_control_information;
ogs_gtp_tlv_f_container_t nbifom_container;
ogs_gtp_tlv_epco_t extended_protocol_configuration_options;
ogs_gtp_tlv_f_teid_t sender_f_teid_for_control_plane;
} ogs_gtp_bearer_resource_command_t;
typedef struct ogs_gtp_bearer_resource_failure_indication_s {
ogs_gtp_tlv_cause_t cause;
ogs_gtp_tlv_ebi_t linked_eps_bearer_id;
ogs_gtp_tlv_pti_t procedure_transaction_id;
ogs_gtp_tlv_indication_t indication_flags;
ogs_gtp_tlv_overload_control_information_t pgw_s_overload_control_information;
ogs_gtp_tlv_overload_control_information_t sgw_s_overload_control_information;
ogs_gtp_tlv_recovery_t recovery;
ogs_gtp_tlv_f_container_t nbifom_container;
} ogs_gtp_bearer_resource_failure_indication_t;
typedef struct ogs_gtp_downlink_data_notification_failure_indication_s {
ogs_gtp_tlv_cause_t cause;
ogs_gtp_tlv_node_type_t originating_node;
@ -1146,6 +1178,8 @@ typedef struct ogs_gtp_message_s {
ogs_gtp_modify_bearer_failure_indication_t modify_bearer_failure_indication;
ogs_gtp_delete_bearer_command_t delete_bearer_command;
ogs_gtp_delete_bearer_failure_indication_t delete_bearer_failure_indication;
ogs_gtp_bearer_resource_command_t bearer_resource_command;
ogs_gtp_bearer_resource_failure_indication_t bearer_resource_failure_indication;
ogs_gtp_downlink_data_notification_failure_indication_t downlink_data_notification_failure_indication;
ogs_gtp_create_bearer_request_t create_bearer_request;
ogs_gtp_create_bearer_response_t create_bearer_response;

View File

@ -232,6 +232,15 @@ void ogs_gtp_send_error_message(
case OGS_GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_RESPONSE_TYPE:
tlv = &errmsg.delete_indirect_data_forwarding_tunnel_response.cause;
break;
case OGS_GTP_MODIFY_BEARER_FAILURE_INDICATION_TYPE:
tlv = &errmsg.modify_bearer_failure_indication.cause;
break;
case OGS_GTP_DELETE_BEARER_FAILURE_INDICATION_TYPE:
tlv = &errmsg.delete_bearer_failure_indication.cause;
break;
case OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE:
tlv = &errmsg.bearer_resource_failure_indication.cause;
break;
default:
ogs_assert_if_reached();
return;

22
lib/gtp/support/cache/tlv-msg-68.py vendored Normal file
View File

@ -0,0 +1,22 @@
ies = []
ies.append({ "ie_type" : "EBI", "ie_value" : "Linked EPS Bearer ID", "presence" : "M", "instance" : "0", "comment" : ""})
ies.append({ "ie_type" : "PTI", "ie_value" : "Procedure Transaction Id", "presence" : "M", "instance" : "0", "comment" : ""})
ies.append({ "ie_type" : "Flow QoS", "ie_value" : "Flow Quality of Service", "presence" : "C", "instance" : "0", "comment" : "This IE shall be included on the S4/S11 interface if the Requested New QoS/Required QoS is included in the corresponding NAS message (see section 9.5.10 and section 9.5.4 in 3GPP TS 24.008 [5]) or the Required traffic flow QoS is included in the corresponding NAS message (see section 8.3.8 and section 8.3.10 in 3GPP TS 24.301 [23]). If SGW receives this IE, SGW shall forward it to PGW across S5/S8 interface."})
ies.append({ "ie_type" : "TAD", "ie_value" : "Traffic Aggregate Description", "presence" : "M", "instance" : "0", "comment" : "The TAD consists of the description of the packet filter(s) for a traffic flow aggregate.MME shall include this IE over S11 interface."})
ies.append({ "ie_type" : "RAT Type", "ie_value" : "RAT Type", "presence" : "C", "instance" : "0", "comment" : "This IE shall be included for MS initiated PDP Context modification procedure and Secondary PDP context activation procedure."})
ies.append({ "ie_type" : "Serving Network", "ie_value" : "Serving Network", "presence" : "O", "instance" : "0", "comment" : "This IE may be included in the MS initiated PDP Context modification procedure.See NOTE 3."})
ies.append({ "ie_type" : "ULI", "ie_value" : "User Location Information", "presence" : "O", "instance" : "0", "comment" : "This IE may be included in the MS initiated PDP Context modification procedure.See NOTE 3."})
type_list["EBI"]["max_instance"] = "1"
ies.append({ "ie_type" : "EBI", "ie_value" : "EPS Bearer ID", "presence" : "C", "instance" : "1", "comment" : "This IE indicates the EPS Bearer that needs to be modified. It shall be included for MS initiated PDP Context modification procedure. For EUTRAN this IE shall be present if it is triggered by the NAS Bearer Resource Modification Request message and its value shall be set to the value of the EPS bearer identity for packet filter IE received in that NAS message."})
ies.append({ "ie_type" : "Indication", "ie_value" : "Indication Flags", "presence" : "CO", "instance" : "0", "comment" : "This IE shall be included if any one of the applicable flags is set to 1.Applicable flags:Change Reporting Support Indication: this flag may be set to 1 in the MS initiated PDP Context modification procedure if the SGSN/MME supports location Info Change Reporting and if the SGSN/MMEs operator policy permits reporting of location change to the operator of the PGW with which the session is established.Direct Tunnel Flag: this flag shall be set to 1 on the S4 interface, if Direct Tunnel is used in the MS initiated PDP Context Modification procedure."})
ies.append({ "ie_type" : "F-TEID", "ie_value" : "S4-U SGSN F-TEID", "presence" : "C", "instance" : "0", "comment" : "This IE shall be included on the S4 interface when direct tunnel is not established in the MS initiated PDP Context modification procedure See NOTE 1"})
ies.append({ "ie_type" : "F-TEID", "ie_value" : "S12 RNC F-TEID", "presence" : "C", "instance" : "1", "comment" : "This IE shall be included on the S4 interface when direct tunnel flag is set to 1 in the MS initiated PDP Context modification procedure. See NOTE 1"})
ies.append({ "ie_type" : "PCO", "ie_value" : "Protocol Configuration Options", "presence" : "O", "instance" : "0", "comment" : "If the UE includes the PCO IE, then the MME/SGSN shall copy the content of this IE transparently from the PCO IE included by the UE. If the SGW receives PCO from the MME/SGSN, the SGW shall forward it to the PGW."})
ies.append({ "ie_type" : "Signalling Priority Indication", "ie_value" : "Signalling Priority Indication ", "presence" : "CO", "instance" : "0", "comment" : "The SGSN/MME shall include this IE on the S4/S11 interface if the UE indicates low access priority during the procedure. The SGW shall forward this IE on the S5/S8 interfaces if received from the MME/SGSN. "})
ies.append({ "ie_type" : "Overload Control Information", "ie_value" : "MME/S4-SGSN's Overload Control Information", "presence" : "O", "instance" : "0", "comment" : "During an overload condition, the MME/S4-SGSN may include this IE on the S11/S4 interface if the overload control feature is supported by the MME/S4-SGSN and is activated for the PLMN to which the PGW belongs (see clause 12.3.11).When present, the MME/S4-SGSN shall provide only one instance of this IE, representing its overload information."})
type_list["Overload Control Information"]["max_instance"] = "1"
ies.append({ "ie_type" : "Overload Control Information", "ie_value" : "SGW's Overload Control Information", "presence" : "O", "instance" : "1", "comment" : "During an overload condition, the SGW may include this IE over the S5/S8 interface if the overload control feature is supported by the SGW and is activated for the PLMN to which the PGW belongs (see clause 12.3.11).When present, the SGW shall provide only one instance of this IE, representing its overload information."})
ies.append({ "ie_type" : "F-Container", "ie_value" : "NBIFOM Container", "presence" : "CO", "instance" : "0", "comment" : "This IE shall be included on the S11/S4 or S2a/S2b interfaces if the MME/S4-SGSN or the TWAN/ePDG receives an NBIFOM Container from the UE as specified in 3GPP TS 24.161 73]. The Container Type shall be set to 4."})
ies.append({ "ie_type" : "ePCO", "ie_value" : "Extended Protocol Configuration Options", "presence" : "O", "instance" : "0", "comment" : "If the UE includes the ePCO IE, then the MME shall copy the content of this IE transparently from the ePCO IE included by the UE. If the SGW receives ePCO from the MME, the SGW shall forward it to the PGW."})
ies.append({ "ie_type" : "F-TEID", "ie_value" : "Sender F-TEID for Control Plane", "presence" : "CO", "instance" : "2", "comment" : "The SGW shall include this IE on the S5/S8 interfaces and set it to the last value sent to the PGW.If the Sender F-TEID for Control Plane is received, the PGW shall only handle the Bearer Resource Command message if the Sender F-TEID for Control Plane in this message is the same as the last Sender F-TEID for Control Plane received on the given interface. "})
msg_list[key]["ies"] = ies

10
lib/gtp/support/cache/tlv-msg-69.py vendored Normal file
View File

@ -0,0 +1,10 @@
ies = []
ies.append({ "ie_type" : "Cause", "ie_value" : "Cause", "presence" : "M", "instance" : "0", "comment" : ""})
ies.append({ "ie_type" : "EBI", "ie_value" : "Linked EPS Bearer ID", "presence" : "M", "instance" : "0", "comment" : "See subclause 6.1.1 Presence requirements of Information Elements."})
ies.append({ "ie_type" : "PTI", "ie_value" : "Procedure Transaction ID", "presence" : "M", "instance" : "0", "comment" : "See subclause 6.1.1 Presence requirements of Information Elements."})
ies.append({ "ie_type" : "Indication", "ie_value" : "Indication Flags", "presence" : "CO", "instance" : "0", "comment" : "This IE shall be included if any one of the applicable flags is set to 1.Applicable flags are:Associate OCI with PGW nodes identity: The PGW shall set this flag to 1 on the S5/S8 interface or S2a/S2b interface if it has included the PGWs Overload Control Information and if this information is to be associated with the node identity (i.e. FQDN or the IP address received from the HSS or DNS during the PGW selection) of the serving PGW. The SGW shall set this flag on the S11/S4 interface if it supports the overload control feature and if the flag is set on the S5/S8 interface.Associate OCI with SGW nodes identity: The SGW shall set this flag to 1 on the S11/S4 interface if it has included the SGWs Overload Control Information and if this information is to be associated with the node identity (i.e. FQDN or the IP address received from the DNS during the SGW selection) of the serving SGW."})
ies.append({ "ie_type" : "Overload Control Information", "ie_value" : "PGW's Overload Control Information", "presence" : "O", "instance" : "0", "comment" : "During an overload condition, the PGW may include this IE on the S5/S8, if the overload control feature is supported by the PGW and is activated for the PLMN to which the access network node, i.e. MME/S4-SGSN for 3GPP access based network, belongs (see clause 12.3.11).When present, the PGW shall provide at least one instance of this IE, representing its overload information. Additionally, the PGW may indicate APN level overload control by providing, one or more instances of this IE, up to maximum of 10, with the same type and instance value, each representing the overload information for a list of APN(s).See NOTE 1, NOTE 2."})
ies.append({ "ie_type" : "Overload Control Information", "ie_value" : "SGW's Overload Control Information", "presence" : "O", "instance" : "1", "comment" : "During an overload condition, the SGW may include this IE over the S11/S4 interface if the overload control feature is supported by the SGW and is activated in the network (see clause 12.3.11).When present, the SGW shall provide only one instance of this IE, representing its overload information."})
ies.append({ "ie_type" : "Recovery", "ie_value" : "Recovery", "presence" : "O", "instance" : "0", "comment" : ""})
ies.append({ "ie_type" : "F-Container", "ie_value" : "NBIFOM Container", "presence" : "CO", "instance" : "0", "comment" : "This IE shall be included on the S5/S8 or S2a/S2b interfaces if the PGW needs to send NBIFOM information as specified in 3GPP TS 23.161 [71]. The Container Type shall be set to 4."})
msg_list[key]["ies"] = ies

View File

@ -307,6 +307,8 @@ msg_list["Create Session Request"]["table"] = 8
msg_list["Create Session Response"]["table"] = 13
msg_list["Create Bearer Request"]["table"] = 18
msg_list["Create Bearer Response"]["table"] = 22
msg_list["Bearer Resource Command"]["table"] = 25
msg_list["Bearer Resource Failure Indication"]["table"] = 27
msg_list["Modify Bearer Request"]["table"] = 29
msg_list["Modify Bearer Response"]["table"] = 33
msg_list["Delete Session Request"]["table"] = 38
@ -365,10 +367,11 @@ type_list["Recovery"]["size"] = 1 # Type : 3
type_list["EBI"]["size"] = 1 # Type : 73
type_list["RAT Type"]["size"] = 1 # Type : 82
type_list["PDN Type"]["size"] = 1 # Type : 99
type_list["PTI"]["size"] = 1 # Type : 100
type_list["Port Number"]["size"] = 2 # Type : 126
type_list["APN Restriction"]["size"] = 1 # Type : 127
type_list["Selection Mode"]["size"] = 1 # Type : 128
type_list["Node Type"]["size"] = 1 # Type : 128
type_list["Node Type"]["size"] = 1 # Type : 135
f = open(outdir + 'message.h', 'w')
output_header_to_file(f)

View File

@ -45,17 +45,23 @@ int16_t ogs_gtp_parse_bearer_qos(
bearer_qos->qci = source->qci;
size++;
/*
* Ch 8.15 Bearer QoS in TS 29.274 v15.9.0
*
* The UL/DL MBR and GBR fields are encoded as kilobits
* per second (1 kbps = 1000 bps) in binary value.
*/
bearer_qos->ul_mbr = ogs_buffer_to_uint64(
(unsigned char *)octet->data + size, 5);
(unsigned char *)octet->data + size, 5) * 1000;
size += 5;
bearer_qos->dl_mbr = ogs_buffer_to_uint64(
(unsigned char *)octet->data + size, 5);
(unsigned char *)octet->data + size, 5) * 1000;
size += 5;
bearer_qos->ul_gbr = ogs_buffer_to_uint64(
(unsigned char *)octet->data + size, 5);
(unsigned char *)octet->data + size, 5) * 1000;
size += 5;
bearer_qos->dl_gbr = ogs_buffer_to_uint64(
(unsigned char *)octet->data + size, 5);
(unsigned char *)octet->data + size, 5) * 1000;
size += 5;
ogs_assert(size == octet->len);
@ -79,13 +85,193 @@ int16_t ogs_gtp_build_bearer_qos(ogs_tlv_octet_t *octet,
memcpy((unsigned char *)octet->data + size, &target, 2);
size += 2;
ogs_uint64_to_buffer(target.ul_mbr, 5, (unsigned char *)octet->data + size);
/*
* Ch 8.15 Bearer QoS in TS 29.274 v15.9.0
*
* The UL/DL MBR and GBR fields are encoded as kilobits
* per second (1 kbps = 1000 bps) in binary value.
*/
ogs_uint64_to_buffer(target.ul_mbr / 1000, 5,
(unsigned char *)octet->data + size);
size += 5;
ogs_uint64_to_buffer(target.dl_mbr, 5, (unsigned char *)octet->data + size);
ogs_uint64_to_buffer(target.dl_mbr / 1000, 5,
(unsigned char *)octet->data + size);
size += 5;
ogs_uint64_to_buffer(target.ul_gbr, 5, (unsigned char *)octet->data + size);
ogs_uint64_to_buffer(target.ul_gbr / 1000, 5,
(unsigned char *)octet->data + size);
size += 5;
ogs_uint64_to_buffer(target.dl_gbr, 5, (unsigned char *)octet->data + size);
ogs_uint64_to_buffer(target.dl_gbr / 1000, 5,
(unsigned char *)octet->data + size);
size += 5;
octet->len = size;
return octet->len;
}
/* 8.16 Flow Quality of Service (Flow QoS) */
uint64_t ogs_gtp_qos_to_kbps(uint8_t br, uint8_t extended, uint8_t extended2)
{
/*
* Octet 12 : 00000000
* 00000000 Use the value indicated by the bit rate in octet 4 and 8
*
* Octet 12 : 00000001 - 00111101
* 256Mbps + the binary coded value in 8 bits * 4Mbps
* giving a range of 260 Mbps to 500 Mbps in 4 Mbps increments.
*
* Octet 12 : 00111110 - 10100001
* 500Mbps + (the binary coded value in 8 bits - 00111101) * 10Mbps
* giving a range of 510 Mbps to 1500 Mbps in 10 Mbps increments.
*
* Octet 12 : 10100010 - 11110110
* 1500Mbps + (the binary coded value in 8 bits - 10100001) * 100Mbps
* giving a range of 1600 Mbps to 10 Gbps Mbps in 100 Mbps increaments.
*/
if (extended2 >= 0b00000001 && extended2 <= 0b00111101) {
return 256*1024 + extended2 * 4*1024;
} else if (extended2 >= 0b00111110 && extended2 <= 0b10100001) {
return 500*1024 + (extended2 - 0b00111101) * 10*1024;
} else if (extended2 >= 0b10100010 && extended2 <= 0b11110110) {
return 1500*1024 + (extended2 - 0b10100001) * 100*1024;
} else if (extended2 > 0b11110110) {
ogs_error("Protocol Error : extended2[%x]", extended2);
return 10*1000*1024; /* 10*1000 Mbps */
/*
* Octet 8
* 00000000 Use the value indicated by the bit rate in octet 4
*
* Octet 8 : 00000001 - 01001010
* 8600 kbps + (the binary coded value in 8 bits) * 100 kbps
* giving a range of 8700 kbps to 16000 kbps in 100 kbps increments.
*
* Octet 8 : 01001011 - 10111010
* 16 Mbps + (the binary coded value in 8 bits - 01001010) * 1 Mbps
* giving a range of 17 Mbps to 128 Mbps in 1 Mbps increments.
*
* Octet 8 : 10111011 - 11111010
* 128 Mbps + (the binary coded value in 8 bits - 10111010) * 2 Mbps
* giving a range of 130 Mbps to 256 Mbps in 2 Mbps increments.
*/
} else if (extended >= 0b00000001 && extended <= 0b01001010) {
return 8600 + extended * 100;
} else if (extended >= 0b01001011 && extended <= 0b10111010) {
return 16*1024 + (extended - 0b01001010) * 1*1024;
} else if (extended >= 0b10111011 && extended <= 0b11111010) {
return 128*1024 + (extended - 0b10111010) * 2*1024;
} else if (extended > 0b11111010) {
ogs_error("Protocol Error : extended[%x]", extended);
return 256*1024; /* 256 Mbps */
/*
* Octet 4
*
* In UE to network direction:
* 00000000 Subscribed maximum bit rate
*
* In network to UE direction:
* 00000000 Reserved
*
* Octet 4 : 00000001 - 00111111
* giving a range of 1 kbps to 63 kbps in 1 kbps increments.
*
* Octet 4 : 01000000 - 01111111
* 64 kbps + (the binary coded value in 8 bits - 01000000) * 8 kbps
* giving a range of 64 kbps to 568 kbps in 8 kbps increments.
*
* Octet 4 : 10000000 - 11111110
* 576 kbps + (the binary coded value in 8 bits 10000000) * 64 kbps
* giving a range of 576 kbps to 8640 kbps in 64 kbps increments.
*/
} else if (br == 0xff) {
return 0; /* 0kbps */
} else if (br >= 0b00000001 && br <= 0b00111111) {
return br;
} else if (br >= 0b01000000 && br <= 0b01111111) {
return 64 + (br - 0b01000000) * 8;
} else if (br >= 0b10000000 && br <= 0b11111110) {
return 576 + (br - 0b10000000) * 64;
}
ogs_fatal("invalid param : br[%d], extended[%d], extended2[%d]",
br, extended, extended2);
ogs_assert_if_reached();
return 0;
}
int16_t ogs_gtp_parse_flow_qos(
ogs_gtp_flow_qos_t *flow_qos, ogs_tlv_octet_t *octet)
{
ogs_gtp_flow_qos_t *source = (ogs_gtp_flow_qos_t *)octet->data;
int16_t size = 0;
ogs_assert(flow_qos);
ogs_assert(octet);
ogs_assert(octet->len == GTP_FLOW_QOS_LEN);
memset(flow_qos, 0, sizeof(ogs_gtp_flow_qos_t));
flow_qos->qci = source->qci;
size++;
/*
* Ch 8.16 Flow QoS in TS 29.274 v15.9.0
*
* The UL/DL MBR and GBR fields are encoded as kilobits
* per second (1 kbps = 1000 bps) in binary value.
*/
flow_qos->ul_mbr = ogs_buffer_to_uint64(
(unsigned char *)octet->data + size, 5) * 1000;
size += 5;
flow_qos->dl_mbr = ogs_buffer_to_uint64(
(unsigned char *)octet->data + size, 5) * 1000;
size += 5;
flow_qos->ul_gbr = ogs_buffer_to_uint64(
(unsigned char *)octet->data + size, 5) * 1000;
size += 5;
flow_qos->dl_gbr = ogs_buffer_to_uint64(
(unsigned char *)octet->data + size, 5) * 1000;
size += 5;
ogs_assert(size == octet->len);
return size;
}
int16_t ogs_gtp_build_flow_qos(ogs_tlv_octet_t *octet,
ogs_gtp_flow_qos_t *flow_qos, void *data, int data_len)
{
ogs_gtp_flow_qos_t target;
int16_t size = 0;
ogs_assert(flow_qos);
ogs_assert(octet);
ogs_assert(data);
ogs_assert(data_len >= GTP_FLOW_QOS_LEN);
octet->data = data;
memcpy(&target, flow_qos, sizeof(ogs_gtp_flow_qos_t));
memcpy((unsigned char *)octet->data + size, &target, 2);
size += 1;
/*
* Ch 8.16 Flow QoS in TS 29.274 v15.9.0
*
* The UL/DL MBR and GBR fields are encoded as kilobits
* per second (1 kbps = 1000 bps) in binary value.
*/
ogs_uint64_to_buffer(target.ul_mbr / 1000, 5,
(unsigned char *)octet->data + size);
size += 5;
ogs_uint64_to_buffer(target.dl_mbr / 1000, 5,
(unsigned char *)octet->data + size);
size += 5;
ogs_uint64_to_buffer(target.ul_gbr / 1000, 5,
(unsigned char *)octet->data + size);
size += 5;
ogs_uint64_to_buffer(target.dl_gbr / 1000, 5,
(unsigned char *)octet->data + size);
size += 5;
octet->len = size;
@ -95,6 +281,153 @@ int16_t ogs_gtp_build_bearer_qos(ogs_tlv_octet_t *octet,
/* 8.19 EPS Bearer Level Traffic Flow Template (Bearer TFT)
* See subclause 10.5.6.12 in 3GPP TS 24.008 [13]. */
int16_t ogs_gtp_parse_tft(ogs_gtp_tft_t *tft, ogs_tlv_octet_t *octet)
{
int16_t size = 0;
int i, j, len = 0;
ogs_assert(tft);
ogs_assert(octet);
memset(tft, 0, sizeof(ogs_gtp_tft_t));
ogs_assert(size+sizeof(tft->flags) <= octet->len);
memcpy(&tft->flags, (unsigned char *)octet->data+size, sizeof(tft->flags));
size++;
for (i = 0; i < tft->num_of_packet_filter; i++) {
ogs_assert(size+sizeof(tft->pf[i].flags) <= octet->len);
memcpy(&tft->pf[i].flags, (unsigned char *)octet->data+size,
sizeof(tft->pf[i].flags));
size += sizeof(tft->pf[i].flags);
ogs_assert(size+sizeof(tft->pf[i].precedence) <= octet->len);
memcpy(&tft->pf[i].precedence, (unsigned char *)octet->data+size,
sizeof(tft->pf[i].precedence));
size += sizeof(tft->pf[i].precedence);
ogs_assert(size+sizeof(tft->pf[i].length) <= octet->len);
memcpy(&tft->pf[i].length, (unsigned char *)octet->data+size,
sizeof(tft->pf[i].length));
size += sizeof(tft->pf[i].length);
j = 0; len = 0;
while(len < tft->pf[i].length) {
ogs_assert(size+len+sizeof(tft->pf[i].component[j].type) <=
octet->len);
memcpy(&tft->pf[i].component[j].type,
(unsigned char *)octet->data+size+len,
sizeof(tft->pf[i].component[j].type));
len += sizeof(tft->pf[i].component[j].type);
switch(tft->pf[i].component[j].type) {
case GTP_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE:
ogs_assert(size+len+sizeof(tft->pf[i].component[j].proto) <=
octet->len);
memcpy(&tft->pf[i].component[j].proto,
(unsigned char *)octet->data+size+len,
sizeof(tft->pf[i].component[j].proto));
len += sizeof(tft->pf[i].component[j].proto);
break;
case GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE:
case GTP_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE:
ogs_assert(size+len+
sizeof(tft->pf[i].component[j].ipv4.addr) <= octet->len);
memcpy(&tft->pf[i].component[j].ipv4.addr,
(unsigned char *)octet->data+size+len,
sizeof(tft->pf[i].component[j].ipv4.addr));
len += sizeof(tft->pf[i].component[j].ipv4.addr);
ogs_assert(size+len+
sizeof(tft->pf[i].component[j].ipv4.mask) <= octet->len);
memcpy(&tft->pf[i].component[j].ipv4.mask,
(unsigned char *)octet->data+size+len,
sizeof(tft->pf[i].component[j].ipv4.mask));
len += sizeof(tft->pf[i].component[j].ipv4.mask);
break;
case GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE:
case GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE:
ogs_assert(size+len+
sizeof(tft->pf[i].component[j].ipv6.addr) <= octet->len);
memcpy(&tft->pf[i].component[j].ipv6.addr,
(unsigned char *)octet->data+size+len,
sizeof(tft->pf[i].component[j].ipv6.addr));
len += sizeof(tft->pf[i].component[j].ipv6.addr);
ogs_assert(size+len+
sizeof(tft->pf[i].component[j].ipv6.prefixlen) <=
octet->len);
memcpy(&tft->pf[i].component[j].ipv6.prefixlen,
(unsigned char *)octet->data+size+len,
sizeof(tft->pf[i].component[j].ipv6.prefixlen));
len += sizeof(tft->pf[i].component[j].ipv6.prefixlen);
break;
case GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_TYPE:
case GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE:
ogs_assert(size+len+
sizeof(tft->pf[i].component[j].ipv6_mask.addr) <=
octet->len);
memcpy(&tft->pf[i].component[j].ipv6_mask.addr,
(unsigned char *)octet->data+size+len,
sizeof(tft->pf[i].component[j].ipv6_mask.addr));
len += sizeof(tft->pf[i].component[j].ipv6_mask.addr);
ogs_assert(size+len+
sizeof(tft->pf[i].component[j].ipv6_mask.mask) <=
octet->len);
memcpy(&tft->pf[i].component[j].ipv6_mask.mask,
(unsigned char *)octet->data+size+len,
sizeof(tft->pf[i].component[j].ipv6_mask.mask));
len += sizeof(tft->pf[i].component[j].ipv6_mask.mask);
break;
case GTP_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE:
case GTP_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE:
ogs_assert(size+len+
sizeof(tft->pf[i].component[j].port.low) <=
octet->len);
memcpy(&tft->pf[i].component[j].port.low,
(unsigned char *)octet->data+size+len,
sizeof(tft->pf[i].component[j].port.low));
tft->pf[i].component[j].port.low =
htobe16(tft->pf[i].component[j].port.low);
len += sizeof(tft->pf[i].component[j].port.low);
break;
case GTP_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE:
case GTP_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE:
ogs_assert(size+len+
sizeof(tft->pf[i].component[j].port.low) <=
octet->len);
memcpy(&tft->pf[i].component[j].port.low,
(unsigned char *)octet->data+size+len,
sizeof(tft->pf[i].component[j].port.low));
tft->pf[i].component[j].port.low =
htobe16(tft->pf[i].component[j].port.low);
len += sizeof(tft->pf[i].component[j].port.low);
ogs_assert(size+len+
sizeof(tft->pf[i].component[j].port.high) <=
octet->len);
memcpy(&tft->pf[i].component[j].port.high,
(unsigned char *)octet->data+size+len,
sizeof(tft->pf[i].component[j].port.high));
tft->pf[i].component[j].port.high =
htobe16(tft->pf[i].component[j].port.high);
len += sizeof(tft->pf[i].component[j].port.high);
break;
default:
ogs_error("Unknown Packet Filter Type(%d)",
tft->pf[i].component[j].type);
return -1;
}
j++;
}
tft->pf[i].num_of_component = j;
size += len;
}
ogs_assert(size == octet->len);
return size;
}
int16_t ogs_gtp_build_tft(
ogs_tlv_octet_t *octet, ogs_gtp_tft_t *tft, void *data, int data_len)
{
@ -111,7 +444,8 @@ int16_t ogs_gtp_build_tft(
memcpy(&target, tft, sizeof(ogs_gtp_tft_t));
ogs_assert(size + sizeof(target.flags) <= data_len);
memcpy((unsigned char *)octet->data + size, &target.flags, sizeof(target.flags));
memcpy((unsigned char *)octet->data + size, &target.flags,
sizeof(target.flags));
size += sizeof(target.flags);
for (i = 0; i < target.num_of_packet_filter; i++) {
@ -137,110 +471,107 @@ int16_t ogs_gtp_build_tft(
&target.pf[i].component[j].type,
sizeof(target.pf[i].component[j].type));
size += sizeof(target.pf[i].component[j].type);
switch(target.pf[i].component[j].type)
{
case GTP_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE:
{
ogs_assert(size +
sizeof(target.pf[i].component[j].proto) <= data_len);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].proto,
sizeof(target.pf[i].component[j].proto));
size += sizeof(target.pf[i].component[j].proto);
break;
}
case GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE:
case GTP_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE:
ogs_assert(size +
sizeof(target.pf[i].component[j].ipv4.addr)
<= data_len);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].ipv4.addr,
sizeof(target.pf[i].component[j].ipv4.addr));
size += sizeof(target.pf[i].component[j].ipv4.addr);
switch(target.pf[i].component[j].type) {
case GTP_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE:
ogs_assert(size +
sizeof(target.pf[i].component[j].proto) <= data_len);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].proto,
sizeof(target.pf[i].component[j].proto));
size += sizeof(target.pf[i].component[j].proto);
break;
case GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE:
case GTP_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE:
ogs_assert(size +
sizeof(target.pf[i].component[j].ipv4.addr)
<= data_len);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].ipv4.addr,
sizeof(target.pf[i].component[j].ipv4.addr));
size += sizeof(target.pf[i].component[j].ipv4.addr);
ogs_assert(size +
sizeof(target.pf[i].component[j].ipv4.mask)
<= data_len);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].ipv4.mask,
sizeof(target.pf[i].component[j].ipv4.mask));
size += sizeof(target.pf[i].component[j].ipv4.mask);
break;
case GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE:
case GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE:
ogs_assert(size +
sizeof(target.pf[i].component[j].ipv6.addr)
<= data_len);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].ipv6.addr,
sizeof(target.pf[i].component[j].ipv6.addr));
size += sizeof(target.pf[i].component[j].ipv6.addr);
ogs_assert(size +
sizeof(target.pf[i].component[j].ipv4.mask)
<= data_len);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].ipv4.mask,
sizeof(target.pf[i].component[j].ipv4.mask));
size += sizeof(target.pf[i].component[j].ipv4.mask);
break;
case GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE:
case GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE:
ogs_assert(size +
sizeof(target.pf[i].component[j].ipv6.addr)
<= data_len);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].ipv6.addr,
sizeof(target.pf[i].component[j].ipv6.addr));
size += sizeof(target.pf[i].component[j].ipv6.addr);
ogs_assert(size +
sizeof(target.pf[i].component[j].ipv6.prefixlen)
<= data_len);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].ipv6.prefixlen,
sizeof(target.pf[i].component[j].ipv6.prefixlen));
size += sizeof(target.pf[i].component[j].ipv6.prefixlen);
break;
case GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE:
ogs_assert(size +
sizeof(target.pf[i].component[j].ipv6_mask.addr)
<= data_len);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].ipv6_mask.addr,
sizeof(target.pf[i].component[j].ipv6_mask.addr));
size += sizeof(target.pf[i].component[j].ipv6_mask.addr);
ogs_assert(size +
sizeof(target.pf[i].component[j].ipv6.prefixlen)
<= data_len);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].ipv6.prefixlen,
sizeof(target.pf[i].component[j].ipv6.prefixlen));
size += sizeof(target.pf[i].component[j].ipv6.prefixlen);
break;
case GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE:
case GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_TYPE:
ogs_assert(size +
sizeof(target.pf[i].component[j].ipv6_mask.addr)
<= data_len);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].ipv6_mask.addr,
sizeof(target.pf[i].component[j].ipv6_mask.addr));
size += sizeof(target.pf[i].component[j].ipv6_mask.addr);
ogs_assert(size +
sizeof(target.pf[i].component[j].ipv6_mask.mask)
<= data_len);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].ipv6_mask.mask,
sizeof(target.pf[i].component[j].ipv6_mask.mask));
size += sizeof(target.pf[i].component[j].ipv6_mask.mask);
break;
case GTP_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE:
case GTP_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE:
ogs_assert(size +
sizeof(target.pf[i].component[j].port.low)
<= data_len);
target.pf[i].component[j].port.low =
htons(target.pf[i].component[j].port.low);
memcpy((unsigned char *)octet->data + size,
ogs_assert(size +
sizeof(target.pf[i].component[j].ipv6_mask.mask)
<= data_len);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].ipv6_mask.mask,
sizeof(target.pf[i].component[j].ipv6_mask.mask));
size += sizeof(target.pf[i].component[j].ipv6_mask.mask);
break;
case GTP_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE:
case GTP_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE:
ogs_assert(size +
sizeof(target.pf[i].component[j].port.low)
<= data_len);
target.pf[i].component[j].port.low =
htobe16(target.pf[i].component[j].port.low);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].port.low,
sizeof(target.pf[i].component[j].port.low));
size += sizeof(target.pf[i].component[j].port.low);
break;
case GTP_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE:
case GTP_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE:
ogs_assert(size +
sizeof(target.pf[i].component[j].port.low)
<= data_len);
target.pf[i].component[j].port.low =
htobe16(target.pf[i].component[j].port.low);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].port.low,
sizeof(target.pf[i].component[j].port.low));
size += sizeof(target.pf[i].component[j].port.low);
break;
case GTP_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE:
case GTP_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE:
ogs_assert(size +
sizeof(target.pf[i].component[j].port.low)
<= data_len);
target.pf[i].component[j].port.low =
htons(target.pf[i].component[j].port.low);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].port.low,
sizeof(target.pf[i].component[j].port.low));
size += sizeof(target.pf[i].component[j].port.low);
size += sizeof(target.pf[i].component[j].port.low);
ogs_assert(size +
sizeof(target.pf[i].component[j].port.high)
<= data_len);
target.pf[i].component[j].port.high =
htons(target.pf[i].component[j].port.high);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].port.high,
sizeof(target.pf[i].component[j].port.high));
size += sizeof(target.pf[i].component[j].port.high);
break;
default:
ogs_error("Unknown Packet Filter Type(%d)",
target.pf[i].component[j].type);
return -1;
ogs_assert(size +
sizeof(target.pf[i].component[j].port.high)
<= data_len);
target.pf[i].component[j].port.high =
htobe16(target.pf[i].component[j].port.high);
memcpy((unsigned char *)octet->data + size,
&target.pf[i].component[j].port.high,
sizeof(target.pf[i].component[j].port.high));
size += sizeof(target.pf[i].component[j].port.high);
break;
default:
ogs_error("Unknown Packet Filter Type(%d)",
target.pf[i].component[j].type);
return -1;
}
}
}
@ -270,50 +601,50 @@ int16_t ogs_gtp_parse_uli(ogs_gtp_uli_t *uli, ogs_tlv_octet_t *octet)
ogs_assert(size + sizeof(uli->cgi) <= octet->len);
memcpy(&uli->cgi,
(unsigned char *)octet->data + size, sizeof(uli->cgi));
uli->cgi.lac = ntohs(uli->cgi.lac);
uli->cgi.ci = ntohs(uli->cgi.ci);
uli->cgi.lac = be16toh(uli->cgi.lac);
uli->cgi.ci = be16toh(uli->cgi.ci);
size += sizeof(uli->cgi);
}
if (uli->flags.sai) {
ogs_assert(size + sizeof(uli->sai) <= octet->len);
memcpy(&uli->sai,
(unsigned char *)octet->data + size, sizeof(uli->sai));
uli->sai.lac = ntohs(uli->sai.lac);
uli->sai.sac = ntohs(uli->sai.sac);
uli->sai.lac = be16toh(uli->sai.lac);
uli->sai.sac = be16toh(uli->sai.sac);
size += sizeof(uli->sai);
}
if (uli->flags.rai) {
ogs_assert(size + sizeof(uli->rai) <= octet->len);
memcpy(&uli->rai,
(unsigned char *)octet->data + size, sizeof(uli->rai));
uli->rai.lac = ntohs(uli->rai.lac);
uli->rai.rac = ntohs(uli->rai.rac);
uli->rai.lac = be16toh(uli->rai.lac);
uli->rai.rac = be16toh(uli->rai.rac);
size += sizeof(uli->rai);
}
if (uli->flags.tai) {
ogs_assert(size + sizeof(uli->tai) <= octet->len);
memcpy(&uli->tai,
(unsigned char *)octet->data + size, sizeof(uli->tai));
uli->tai.tac = ntohs(uli->tai.tac);
uli->tai.tac = be16toh(uli->tai.tac);
size += sizeof(uli->tai);
}
if (uli->flags.e_cgi) {
ogs_assert(size + sizeof(uli->e_cgi) <= octet->len);
memcpy(&uli->e_cgi,
(unsigned char *)octet->data + size, sizeof(uli->e_cgi));
uli->e_cgi.cell_id = ntohl(uli->e_cgi.cell_id);
uli->e_cgi.cell_id = be32toh(uli->e_cgi.cell_id);
size += sizeof(uli->e_cgi);
}
if (uli->flags.lai) {
ogs_assert(size + sizeof(uli->lai) <= octet->len);
memcpy(&uli->lai,
(unsigned char *)octet->data + size, sizeof(uli->lai));
uli->lai.lac = ntohs(uli->lai.lac);
uli->lai.lac = be16toh(uli->lai.lac);
size += sizeof(uli->lai);
}
ogs_assert(size == octet->len);
return size;
}
int16_t ogs_gtp_build_uli(
@ -337,45 +668,45 @@ int16_t ogs_gtp_build_uli(
if (target.flags.cgi) {
ogs_assert(size + sizeof(target.cgi) <= data_len);
target.cgi.lac = htons(target.cgi.lac);
target.cgi.ci = htons(target.cgi.ci);
target.cgi.lac = htobe16(target.cgi.lac);
target.cgi.ci = htobe16(target.cgi.ci);
memcpy((unsigned char *)octet->data + size,
&target.cgi, sizeof(target.cgi));
size += sizeof(target.cgi);
}
if (target.flags.sai) {
ogs_assert(size + sizeof(target.sai) <= data_len);
target.sai.lac = htons(target.sai.lac);
target.sai.sac = htons(target.sai.sac);
target.sai.lac = htobe16(target.sai.lac);
target.sai.sac = htobe16(target.sai.sac);
memcpy((unsigned char *)octet->data + size,
&target.sai, sizeof(target.sai));
size += sizeof(target.sai);
}
if (target.flags.rai) {
ogs_assert(size + sizeof(target.rai) <= data_len);
target.rai.lac = htons(target.rai.lac);
target.rai.rac = htons(target.rai.rac);
target.rai.lac = htobe16(target.rai.lac);
target.rai.rac = htobe16(target.rai.rac);
memcpy((unsigned char *)octet->data + size,
&target.rai, sizeof(target.rai));
size += sizeof(target.rai);
}
if (target.flags.tai) {
ogs_assert(size + sizeof(target.tai) <= data_len);
target.tai.tac = htons(target.tai.tac);
target.tai.tac = htobe16(target.tai.tac);
memcpy((unsigned char *)octet->data + size,
&target.tai, sizeof(target.tai));
size += sizeof(target.tai);
}
if (target.flags.e_cgi) {
ogs_assert(size + sizeof(target.e_cgi) <= data_len);
target.e_cgi.cell_id = htonl(target.e_cgi.cell_id);
target.e_cgi.cell_id = htobe32(target.e_cgi.cell_id);
memcpy((unsigned char *)octet->data + size,
&target.e_cgi, sizeof(target.e_cgi));
size += sizeof(target.e_cgi);
}
if (target.flags.lai) {
ogs_assert(size + sizeof(target.lai) <= data_len);
target.lai.lac = htons(target.lai.lac);
target.lai.lac = htobe16(target.lai.lac);
memcpy((unsigned char *)octet->data + size,
&target.lai, sizeof(target.lai));
size += sizeof(target.lai);

View File

@ -195,6 +195,31 @@ int16_t ogs_gtp_parse_bearer_qos(
int16_t ogs_gtp_build_bearer_qos(ogs_tlv_octet_t *octet,
ogs_gtp_bearer_qos_t *bearer_qos, void *data, int data_len);
/* 8.16 Flow Quality of Service (Flow QoS) */
#define GTP_FLOW_QOS_LEN 21
typedef struct ogs_gtp_flow_qos_s {
uint8_t qci; /* specified in 3GPP TS 23.203 [48]. */
/* specified in 3GPP TS 36.413 [10]. */
uint64_t ul_mbr;
uint64_t dl_mbr;
uint64_t ul_gbr;
uint64_t dl_gbr;
/* NOTE : The encoding in 3GPP TS 24.301 [23] and 3GPP TS 36.413 [10]
* is different from the encoding within this specification. */
} __attribute__ ((packed)) ogs_gtp_flow_qos_t;
#define ogs_gtp_qos_to_bps(br, extended, extended2) \
ogs_gtp_qos_to_kbps(br, extended, extended2) * 1024;
uint64_t ogs_gtp_qos_to_kbps(uint8_t br, uint8_t extended, uint8_t extended2);
int16_t ogs_gtp_parse_flow_qos(
ogs_gtp_flow_qos_t *flow_qos, ogs_tlv_octet_t *octet);
int16_t ogs_gtp_build_flow_qos(ogs_tlv_octet_t *octet,
ogs_gtp_flow_qos_t *flow_qos, void *data, int data_len);
/* 8.17 RAT Type */
#define OGS_GTP_RAT_TYPE_UTRAN 1
#define OGS_GTP_RAT_TYPE_GERAN 2
@ -277,6 +302,7 @@ ED3(uint8_t code:3;,
} pf[OGS_MAX_NUM_OF_PACKET_FILTER];
} ogs_gtp_tft_t;
int16_t ogs_gtp_parse_tft(ogs_gtp_tft_t *tft, ogs_tlv_octet_t *octet);
int16_t ogs_gtp_build_tft(
ogs_tlv_octet_t *octet, ogs_gtp_tft_t *tft, void *data, int data_len);

View File

@ -19,14 +19,11 @@
#include "ogs-gtp.h"
#define GTP_MIN_XACT_ID 1
#define GTP_MAX_XACT_ID 0x800000
#define GTP_T3_RESPONSE_DURATION ogs_time_from_sec(3) /* 3 seconds */
#define GTP_T3_RESPONSE_RETRY_COUNT 3
#define GTP_T3_RESPONSE_DURATION ogs_time_from_sec(3) /* 3 seconds */
#define GTP_T3_RESPONSE_RETRY_COUNT 3
#define GTP_T3_DUPLICATED_DURATION \
(GTP_T3_RESPONSE_DURATION * GTP_T3_RESPONSE_RETRY_COUNT) /* 9 seconds */
#define GTP_T3_DUPLICATED_RETRY_COUNT 1
#define GTP_T3_DUPLICATED_RETRY_COUNT 1
typedef enum {
GTP_XACT_UNKNOWN_STAGE,
@ -81,6 +78,7 @@ ogs_gtp_xact_t *ogs_gtp_xact_local_create(ogs_gtp_node_t *gnode,
ogs_gtp_xact_t *xact = NULL;
ogs_assert(gnode);
ogs_assert(hdesc);
ogs_pool_alloc(&pool, &xact);
ogs_assert(xact);
@ -88,7 +86,13 @@ ogs_gtp_xact_t *ogs_gtp_xact_local_create(ogs_gtp_node_t *gnode,
xact->index = ogs_pool_index(&pool, xact);
xact->org = OGS_GTP_LOCAL_ORIGINATOR;
xact->xid = OGS_NEXT_ID(g_xact_id, GTP_MIN_XACT_ID, GTP_MAX_XACT_ID);
xact->xid = OGS_NEXT_ID(g_xact_id,
OGS_GTP_MIN_XACT_ID, OGS_GTP_CMD_XACT_ID);
if (hdesc->type == OGS_GTP_MODIFY_BEARER_COMMAND_TYPE ||
hdesc->type == OGS_GTP_DELETE_BEARER_COMMAND_TYPE ||
hdesc->type == OGS_GTP_BEARER_RESOURCE_COMMAND_TYPE) {
xact->xid |= OGS_GTP_CMD_XACT_ID;
}
xact->gnode = gnode;
xact->cb = cb;
xact->data = data;
@ -684,7 +688,7 @@ static ogs_gtp_xact_stage_t ogs_gtp_xact_get_stage(uint8_t type, uint32_t xid)
case OGS_GTP_CREATE_BEARER_REQUEST_TYPE:
case OGS_GTP_UPDATE_BEARER_REQUEST_TYPE:
case OGS_GTP_DELETE_BEARER_REQUEST_TYPE:
if (xid & GTP_MAX_XACT_ID)
if (xid & OGS_GTP_CMD_XACT_ID)
stage = GTP_XACT_INTERMEDIATE_STAGE;
else
stage = GTP_XACT_INITIAL_STAGE;
@ -731,10 +735,17 @@ ogs_gtp_xact_t *ogs_gtp_xact_find_by_xid(
list = &gnode->local_list;
break;
case GTP_XACT_FINAL_STAGE:
if (xid & GTP_MAX_XACT_ID)
list = &gnode->remote_list;
else
if (xid & OGS_GTP_CMD_XACT_ID) {
if (type == OGS_GTP_MODIFY_BEARER_FAILURE_INDICATION_TYPE ||
type == OGS_GTP_DELETE_BEARER_FAILURE_INDICATION_TYPE ||
type == OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE) {
list = &gnode->local_list;
} else {
list = &gnode->remote_list;
}
} else {
list = &gnode->local_list;
}
break;
default:
ogs_assert_if_reached();

View File

@ -28,6 +28,26 @@
extern "C" {
#endif
/*
* p225-226 Chapter 7.6 in TS 29.274 V15.9.0
*
* A Sequence Number used for a Command message shall have the most significant
* bit set to 1. A Sequence Number in a message, which was triggered by
* a Command message, as well as respective Triggered Reply message
* shall have the same Sequence Number as the Command message
* (i.e. shall also have the most significant bit set to 1).
*
* This setting of the most significant bit of the Sequence Number is done
* to avoid potential clashes between the Sequence Number selected for
* a Command message, and the Sequence Number selected by a GTPv2 peer
* for a Request message, which was not triggered by a Command message.
*
* A Sequence Number used for a Request message, which was not triggered
* by a Command message shall have the most significant bit set to 0.
*/
#define OGS_GTP_MIN_XACT_ID 1
#define OGS_GTP_CMD_XACT_ID 0x800000
/**
* Transaction context
*/

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by nas-message.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2019-11-29 20:48:26.777198 by acetcom
* Created on: 2019-12-27 13:52:39.321365 by acetcom
* from 24301-d80.docx
******************************************************************************/

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by nas-message.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2019-11-29 20:48:26.787333 by acetcom
* Created on: 2019-12-27 13:52:39.331386 by acetcom
* from 24301-d80.docx
******************************************************************************/

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by nas-message.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2019-11-29 20:48:26.763343 by acetcom
* Created on: 2019-12-27 13:52:39.307616 by acetcom
* from 24301-d80.docx
******************************************************************************/

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by nas-message.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2019-11-29 20:48:26.761226 by acetcom
* Created on: 2019-12-27 13:52:39.304361 by acetcom
* from 24301-d80.docx
******************************************************************************/

View File

@ -20,7 +20,7 @@
/*******************************************************************************
* This file had been created by nas-message.py script v0.1.0
* Please do not modify this file but regenerate it via script.
* Created on: 2019-11-29 20:48:26.769392 by acetcom
* Created on: 2019-12-27 13:52:39.313560 by acetcom
* from 24301-d80.docx
******************************************************************************/
@ -51,7 +51,6 @@ extern "C" {
#define OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM 0x7
#define OGS_NAS_EPS_BEARER_IDENTITY_UNASSIGNED 0
#define OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED 0
typedef struct ogs_nas_emm_header_s {
ED2(uint8_t security_header_type:4;,

View File

@ -519,7 +519,6 @@ extern "C" {
#define OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM 0x7
#define OGS_NAS_EPS_BEARER_IDENTITY_UNASSIGNED 0
#define OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED 0
typedef struct ogs_nas_emm_header_s {
ED2(uint8_t security_header_type:4;,

View File

@ -44,15 +44,14 @@ void *ogs_nas_to_plmn_id(ogs_plmn_id_t *plmn_id, ogs_nas_plmn_id_t *ogs_nas_plmn
return plmn_id;
}
static uint8_t br_calculate(
static uint8_t nas_ambr_from_kbps(
uint8_t *br, uint8_t *extended, uint8_t *extended2,
uint64_t input)
{
uint8_t length = 0;
/* Octet 3 : 00000000 Reserved, 11111111 0kbps */
if (input < 1)
{
if (input < 1) {
*br = 0xff;
length = ogs_max(length, 1);
@ -67,18 +66,18 @@ static uint8_t br_calculate(
* Octet 7 : 00000001 - 11111110
* The APN-AMBR is
* (the binary coded value in 8 bits) * 256 Mbps +
* (the value indicated by the APN-AMBR for downlink
* and APN-AMBR for downlink (extended) in octets 3 and 5),
* "the value indicated by the APN-AMBR for downlink
* and APN-AMBR for downlink (extended) in octets 3 and 5",
*
* giving a range of 256 Mbps to 65280 Mbps. */
if (input > (65200*1024))
{
if (input > (65200*1024)) {
ogs_error("Overflow : %ldkbps > 65200Mbps", (long)input);
*extended2 = 0b11111110;
length = ogs_max(length, 3);
input %= (256*1024);
}
else if (input >= (256*1024) && input <= (65200*1024))
{
else if (input >= (256*1024) && input <= (65200*1024)) {
*extended2 = input / (256*1024);
length = ogs_max(length, 3);
@ -88,8 +87,7 @@ static uint8_t br_calculate(
/* Octet 3 : 00000001 - 00111111
* The APN-AMBR is binary coded in 8 bits, using a granularity of 1 kbps
* giving a range of values from 1 kbps to 63 kbps in 1 kbps increments. */
if (input >= 1 && input <= 63)
{
if (input >= 1 && input <= 63) {
*br = input;
length = ogs_max(length, 1);
}
@ -98,14 +96,12 @@ static uint8_t br_calculate(
* 64 kbps + ((the binary coded value in 8 bits 01000000) * 8 kbps)
* giving a range of values from 64 kbps to 568 kbps
* in 8 kbps increments. */
else if (input >= 64 && input <= 568)
{
else if (input >= 64 && input <= 568) {
*br = ((input - 64) / 8) + 0b01000000;
length = ogs_max(length, 1);
}
/* Set to 568 Kbps */
else if (input > 568 && input < 576)
{
else if (input > 568 && input < 576) {
*br = 0b01111111;
length = ogs_max(length, 1);
}
@ -114,14 +110,12 @@ static uint8_t br_calculate(
* 576 kbps + ((the binary coded value in 8 bits 10000000) * 64 kbps)
* giving a range of values from 576 kbps to 8640 kbps
* in 64 kbps increments. */
else if (input >= 576 && input <= 8640)
{
else if (input >= 576 && input <= 8640) {
*br = ((input - 576) / 64) + 0b10000000;
length = ogs_max(length, 1);
}
/* Set to 8640 Kbps */
else if (input > 8640 && input < 8700)
{
else if (input > 8640 && input < 8700) {
*br = 0b11111110;
length = ogs_max(length, 1);
}
@ -142,15 +136,13 @@ static uint8_t br_calculate(
* giving a range of values from 8700 kbps to 16000 kbps
* in 100 kbps increments.
*/
else if (input >= 8700 && input <= 16000)
{
else if (input >= 8700 && input <= 16000) {
*br = 0b11111110;
*extended = ((input - 8600) / 100);
length = ogs_max(length, 2);
}
/* Set to 16000 Kbps */
else if (input > 16000 && input < (17*1024))
{
else if (input > 16000 && input < (17*1024)) {
*br = 0b11111110;
*extended = 0b01001010;
length = ogs_max(length, 2);
@ -160,15 +152,13 @@ static uint8_t br_calculate(
* 16 Mbps + ((the binary coded value in 8 bits - 01001010) * 1 Mbps),
* giving a range of values from 17 Mbps to 128 Mbps
* in 1 Mbps increments. */
else if (input >= (17*1024) && input <= (128*1024))
{
else if (input >= (17*1024) && input <= (128*1024)) {
*br = 0b11111110;
*extended = ((input - (16*1024)) / (1*1024)) + 0b01001010;
length = ogs_max(length, 2);
}
/* Set to 128 Mbps */
else if (input > (128*1024) && input < (130*1024))
{
else if (input > (128*1024) && input < (130*1024)) {
*br = 0b11111110;
*extended = 0b10111010;
length = ogs_max(length, 2);
@ -178,8 +168,7 @@ static uint8_t br_calculate(
* 128 Mbps + ((the binary coded value in 8 bits - 10111010) * 2 Mbps),
* giving a range of values from 130 Mbps to 256 Mbps
* in 2 Mbps increments. */
else if (input >= (130*1024) && input <= (256*1024))
{
else if (input >= (130*1024) && input <= (256*1024)) {
*br = 0b11111110;
*extended = ((input - (128*1024)) / (2*1024)) + 0b10111010;
length = ogs_max(length, 2);
@ -188,6 +177,187 @@ static uint8_t br_calculate(
return length;
}
static uint8_t nas_qos_from_kbps(
uint8_t *br, uint8_t *extended, uint8_t *extended2,
uint64_t input)
{
uint8_t length = 0;
/*
* Octet 4
* 11111111 0kbps
*/
if (input < 1) {
*br = 0xff;
length = ogs_max(length, 1);
return length;
}
/*
* Octet 4
*
* In UE to network direction:
* 00000000 Subscribed maximum bit rate
*
* In network to UE direction:
* 00000000 Reserved
*
* Octet 4 : 00000001 - 00111111
* giving a range of 1 kbps to 63 kbps in 1 kbps increments.
*
* Octet 4 : 01000000 - 01111111
* 64 kbps + (the binary coded value in 8 bits - 01000000) * 8 kbps
* giving a range of 64 kbps to 568 kbps in 8 kbps increments.
*
* Octet 4 : 10000000 - 11111110
* 576 kbps + (the binary coded value in 8 bits 10000000) * 64 kbps
* giving a range of 576 kbps to 8640 kbps in 64 kbps increments.
*/
/* giving a range of 1 kbps to 63 kbps in 1 kbps increments. */
if (input >= 1 && input <= 63) {
*br = input;
length = ogs_max(length, 1);
}
/* giving a range of 64 kbps to 568 kbps in 8 kbps increments. */
else if (input >= 64 && input <= 568) {
*br = ((input - 64) / 8) + 0b01000000;
length = ogs_max(length, 1);
}
/* Set to 568 Kbps */
else if (input > 568 && input < 576) {
*br = 0b01111111;
length = ogs_max(length, 1);
}
/* giving a range of 576 kbps to 8640 kbps in 64 kbps increments. */
else if (input >= 576 && input <= 8640) {
*br = ((input - 576) / 64) + 0b10000000;
length = ogs_max(length, 1);
}
/* Set to 8640 Kbps */
else if (input > 8640 && input < 8700) {
*br = 0b11111110;
length = ogs_max(length, 1);
}
/*
* Octet 8
* 00000000 Use the value indicated by the bit rate in octet 4
*
* Octet 8 : 00000001 - 01001010
* 8600 kbps + (the binary coded value in 8 bits) * 100 kbps
* giving a range of 8700 kbps to 16000 kbps in 100 kbps increments.
*
* Octet 8 : 01001011 - 10111010
* 16 Mbps + (the binary coded value in 8 bits - 01001010) * 1 Mbps
* giving a range of 17 Mbps to 128 Mbps in 1 Mbps increments.
*
* Octet 8 : 10111011 - 11111010
* 128 Mbps + (the binary coded value in 8 bits - 10111010) * 2 Mbps
* giving a range of 130 Mbps to 256 Mbps in 2 Mbps increments.
*/
/* giving a range of 8700 kbps to 16000 kbps in 100 kbps increments. */
else if (input >= 8700 && input <= 16000) {
*br = 0b11111110;
*extended = ((input - 8600) / 100);
length = ogs_max(length, 2);
}
/* Set to 16000 Kbps */
else if (input > 16000 && input < (17*1024)) {
*br = 0b11111110;
*extended = 0b01001010;
length = ogs_max(length, 2);
}
/* giving a range of 17 Mbps to 128 Mbps in 1 Mbps increments. */
else if (input >= (17*1024) && input <= (128*1024)) {
*br = 0b11111110;
*extended = ((input - (16*1024)) / (1*1024)) + 0b01001010;
length = ogs_max(length, 2);
}
/* Set to 128 Mbps */
else if (input > (128*1024) && input < (130*1024)) {
*br = 0b11111110;
*extended = 0b10111010;
length = ogs_max(length, 2);
}
/* giving a range of 130 Mbps to 256 Mbps in 2 Mbps increments. */
else if (input >= (130*1024) && input <= (256*1024)) {
*br = 0b11111110;
*extended = ((input - (128*1024)) / (2*1024)) + 0b10111010;
length = ogs_max(length, 2);
}
/* Set to 256 Mbps */
else if (input > (256*1024) && input < (260*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
length = ogs_max(length, 2);
}
/*
* Octet 12 : 00000000
* 00000000 Use the value indicated by the bit rate in octet 4 and 8
*
* Octet 12 : 00000001 - 00111101
* 256Mbps + the binary coded value in 8 bits * 4Mbps
* giving a range of 260 Mbps to 500 Mbps in 4 Mbps increments.
*
* Octet 12 : 00111110 - 10100001
* 500Mbps + (the binary coded value in 8 bits - 00111101) * 10Mbps
* giving a range of 510 Mbps to 1500 Mbps in 10 Mbps increments.
*
* Octet 12 : 10100010 - 11110110
* 1500Mbps + (the binary coded value in 8 bits - 10100001) * 100Mbps
* giving a range of 1600 Mbps to 10 Gbps Mbps in 100 Mbps increaments.
*/
/* giving a range of values from 260M to 500M in 4M increments */
else if (input >= (260*1024) && input <= (500*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
*extended2 = (input - (256*1024)) / (4*1024);
length = ogs_max(length, 3);
}
/* if a range of values from 500M to 510M */
else if (input > (500*1024) && input < (510*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
*extended2 = 0b00111101;
length = ogs_max(length, 3);
}
/* giving a range of values from 510M to 1500M in 10M increments */
else if (input >= (510*1024) && input <= (1500*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
*extended2 = (input - (500*1024)) / (10*1024) + 0b00111101;
length = ogs_max(length, 3);
}
/* if a range of values from 1500M to 1600M */
else if (input > (1500*1024) && input < (1600*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
*extended2 = 0b10100001;
length = ogs_max(length, 3);
}
/* giving a range of values from 1600M to 10000M in 100M increments */
else if (input >= (1600*1024) && input <= (10*1000*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
*extended2 = (input - (1500*1024)) / (100*1024) + 0b10100001;
length = ogs_max(length, 3);
}
/* if the sending entity want to indicate BR higher than 10000Mbps */
else if (input > (10*1000*1024)) {
*br = 0b11111110;
*extended = 0b11111010;
*extended2 = 0b11110110;
length = ogs_max(length, 3);
}
return length;
}
void apn_ambr_build(
ogs_nas_apn_aggregate_maximum_bit_rate_t *apn_aggregate_maximum_bit_rate,
uint32_t dl_apn_ambr, uint32_t ul_apn_ambr)
@ -200,13 +370,13 @@ void apn_ambr_build(
memset(apn_aggregate_maximum_bit_rate, 0,
sizeof(ogs_nas_apn_aggregate_maximum_bit_rate_t));
length = ogs_max(length, br_calculate(
length = ogs_max(length, nas_ambr_from_kbps(
&apn_aggregate_maximum_bit_rate->dl_apn_ambr,
&apn_aggregate_maximum_bit_rate->dl_apn_ambr_extended,
&apn_aggregate_maximum_bit_rate->dl_apn_ambr_extended2,
dl_apn_ambr));
length = ogs_max(length, br_calculate(
length = ogs_max(length, nas_ambr_from_kbps(
&apn_aggregate_maximum_bit_rate->ul_apn_ambr,
&apn_aggregate_maximum_bit_rate->ul_apn_ambr_extended,
&apn_aggregate_maximum_bit_rate->ul_apn_ambr_extended2,
@ -230,28 +400,28 @@ void eps_qos_build(ogs_nas_eps_quality_of_service_t *eps_qos, uint8_t qci,
eps_qos->qci = qci;
if (dl_mbr)
length = ogs_max(length, br_calculate(
length = ogs_max(length, nas_qos_from_kbps(
&eps_qos->dl_mbr,
&eps_qos->dl_mbr_extended,
&eps_qos->dl_mbr_extended2,
dl_mbr));
if (ul_mbr)
length = ogs_max(length, br_calculate(
length = ogs_max(length, nas_qos_from_kbps(
&eps_qos->ul_mbr,
&eps_qos->ul_mbr_extended,
&eps_qos->ul_mbr_extended2,
ul_mbr));
if (dl_gbr)
length = ogs_max(length, br_calculate(
length = ogs_max(length, nas_qos_from_kbps(
&eps_qos->dl_gbr,
&eps_qos->dl_gbr_extended,
&eps_qos->dl_gbr_extended2,
dl_gbr));
if (ul_gbr)
length = ogs_max(length, br_calculate(
length = ogs_max(length, nas_qos_from_kbps(
&eps_qos->ul_gbr,
&eps_qos->ul_gbr_extended,
&eps_qos->ul_gbr_extended2,

View File

@ -29,7 +29,7 @@ ogs_pkbuf_t *esm_build_pdn_connectivity_reject(
{
mme_ue_t *mme_ue = NULL;
ogs_nas_message_t message;
ogs_nas_pdn_connectivity_reject_t *pdn_connectivity_reject =
ogs_nas_pdn_connectivity_reject_t *pdn_connectivity_reject =
&message.esm.pdn_connectivity_reject;
ogs_assert(sess);
@ -42,7 +42,7 @@ ogs_pkbuf_t *esm_build_pdn_connectivity_reject(
memset(&message, 0, sizeof(message));
if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) {
message.h.security_header_type =
message.h.security_header_type =
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
}
@ -77,7 +77,7 @@ ogs_pkbuf_t *esm_build_information_request(mme_bearer_t *bearer)
mme_ue->imsi_bcd, sess->pti, bearer->ebi);
memset(&message, 0, sizeof(message));
message.h.security_header_type =
message.h.security_header_type =
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
@ -93,13 +93,13 @@ ogs_pkbuf_t *esm_build_activate_default_bearer_context_request(
{
ogs_nas_message_t message;
ogs_nas_activate_default_eps_bearer_context_request_t
*activate_default_eps_bearer_context_request =
*activate_default_eps_bearer_context_request =
&message.esm.activate_default_eps_bearer_context_request;
ogs_nas_eps_quality_of_service_t *eps_qos =
&activate_default_eps_bearer_context_request->eps_qos;
ogs_nas_access_point_name_t *access_point_name =
&activate_default_eps_bearer_context_request->access_point_name;
ogs_nas_pdn_address_t *pdn_address =
ogs_nas_pdn_address_t *pdn_address =
&activate_default_eps_bearer_context_request->pdn_address;
ogs_nas_apn_aggregate_maximum_bit_rate_t *apn_ambr =
&activate_default_eps_bearer_context_request->apn_ambr;
@ -118,6 +118,11 @@ ogs_pkbuf_t *esm_build_activate_default_bearer_context_request(
ogs_assert(pdn);
bearer = mme_default_bearer_in_sess(sess);
ogs_assert(bearer);
if (mme_bearer_next(bearer) != NULL) {
ogs_error("PDN connectivity duplicated");
return NULL;
}
ogs_assert(mme_bearer_next(bearer) == NULL);
ogs_debug("[ESM] Activate default bearer context request");
@ -126,14 +131,14 @@ ogs_pkbuf_t *esm_build_activate_default_bearer_context_request(
memset(&message, 0, sizeof(message));
if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) {
message.h.security_header_type =
message.h.security_header_type =
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
}
message.esm.h.eps_bearer_identity = bearer->ebi;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
message.esm.h.procedure_transaction_identity = sess->pti;
message.esm.h.message_type =
message.esm.h.message_type =
OGS_NAS_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST;
memcpy(&bearer->qos, &pdn->qos, sizeof(ogs_qos_t));
@ -197,14 +202,14 @@ ogs_pkbuf_t *esm_build_activate_dedicated_bearer_context_request(
ogs_nas_message_t message;
ogs_nas_activate_dedicated_eps_bearer_context_request_t
*activate_dedicated_eps_bearer_context_request =
*activate_dedicated_eps_bearer_context_request =
&message.esm.activate_dedicated_eps_bearer_context_request;
ogs_nas_linked_eps_bearer_identity_t *linked_ebi =
&activate_dedicated_eps_bearer_context_request->
linked_eps_bearer_identity;
ogs_nas_eps_quality_of_service_t *eps_qos =
&activate_dedicated_eps_bearer_context_request->eps_qos;
ogs_nas_traffic_flow_template_t *tft =
ogs_nas_traffic_flow_template_t *tft =
&activate_dedicated_eps_bearer_context_request->tft;
ogs_assert(bearer);
@ -218,13 +223,13 @@ ogs_pkbuf_t *esm_build_activate_dedicated_bearer_context_request(
mme_ue->imsi_bcd, bearer->ebi, linked_bearer->ebi);
memset(&message, 0, sizeof(message));
message.h.security_header_type =
message.h.security_header_type =
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
message.esm.h.eps_bearer_identity = bearer->ebi;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
message.esm.h.procedure_transaction_identity = 0;
message.esm.h.message_type =
message.esm.h.message_type =
OGS_NAS_ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST;
linked_ebi->eps_bearer_identity = linked_bearer->ebi;
@ -248,11 +253,11 @@ ogs_pkbuf_t *esm_build_modify_bearer_context_request(
ogs_nas_message_t message;
ogs_nas_modify_eps_bearer_context_request_t
*modify_eps_bearer_context_request =
*modify_eps_bearer_context_request =
&message.esm.modify_eps_bearer_context_request;
ogs_nas_eps_quality_of_service_t *new_eps_qos =
&modify_eps_bearer_context_request->new_eps_qos;
ogs_nas_traffic_flow_template_t *tft =
ogs_nas_traffic_flow_template_t *tft =
&modify_eps_bearer_context_request->tft;
ogs_assert(bearer);
@ -266,7 +271,7 @@ ogs_pkbuf_t *esm_build_modify_bearer_context_request(
mme_ue->imsi_bcd, sess->pti, bearer->ebi);
memset(&message, 0, sizeof(message));
message.h.security_header_type =
message.h.security_header_type =
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
message.esm.h.eps_bearer_identity = bearer->ebi;
@ -302,7 +307,7 @@ ogs_pkbuf_t *esm_build_deactivate_bearer_context_request(
ogs_nas_message_t message;
ogs_nas_deactivate_eps_bearer_context_request_t
*deactivate_eps_bearer_context_request =
*deactivate_eps_bearer_context_request =
&message.esm.deactivate_eps_bearer_context_request;
ogs_assert(bearer);
@ -317,7 +322,7 @@ ogs_pkbuf_t *esm_build_deactivate_bearer_context_request(
ogs_debug(" Cause[%d]", esm_cause);
memset(&message, 0, sizeof(message));
message.h.security_header_type =
message.h.security_header_type =
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
message.esm.h.eps_bearer_identity = bearer->ebi;
@ -329,3 +334,87 @@ ogs_pkbuf_t *esm_build_deactivate_bearer_context_request(
return nas_security_encode(mme_ue, &message);
}
ogs_pkbuf_t *esm_build_bearer_resource_allocation_reject(
mme_bearer_t *bearer, ogs_nas_esm_cause_t esm_cause)
{
mme_ue_t *mme_ue = NULL;
mme_sess_t *sess = NULL;
ogs_nas_message_t message;
ogs_nas_bearer_resource_allocation_reject_t
*bearer_resource_allocation_reject =
&message.esm.bearer_resource_allocation_reject;
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
ogs_debug("[ESM] Bearer resource allocation reject");
ogs_debug(" IMSI[%s] PTI[%d] Cause[%d]",
mme_ue->imsi_bcd, sess->pti, esm_cause);
memset(&message, 0, sizeof(message));
if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) {
message.h.security_header_type =
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
}
message.esm.h.eps_bearer_identity = 0;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
message.esm.h.procedure_transaction_identity = sess->pti;
message.esm.h.message_type = OGS_NAS_BEARER_RESOURCE_ALLOCATION_REJECT;
bearer_resource_allocation_reject->esm_cause = esm_cause;
if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) {
return nas_security_encode(mme_ue, &message);
} else {
return ogs_nas_plain_encode(&message);
}
}
ogs_pkbuf_t *esm_build_bearer_resource_modification_reject(
mme_bearer_t *bearer, ogs_nas_esm_cause_t esm_cause)
{
mme_ue_t *mme_ue = NULL;
mme_sess_t *sess = NULL;
ogs_nas_message_t message;
ogs_nas_bearer_resource_modification_reject_t
*bearer_resource_modification_reject =
&message.esm.bearer_resource_modification_reject;
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
ogs_debug("[ESM] Bearer resource modification reject");
ogs_debug(" IMSI[%s] PTI[%d] Cause[%d]",
mme_ue->imsi_bcd, sess->pti, esm_cause);
memset(&message, 0, sizeof(message));
if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) {
message.h.security_header_type =
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
}
message.esm.h.eps_bearer_identity = 0;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
message.esm.h.procedure_transaction_identity = sess->pti;
message.esm.h.message_type = OGS_NAS_BEARER_RESOURCE_MODIFICATION_REJECT;
bearer_resource_modification_reject->esm_cause = esm_cause;
if (OGS_FSM_CHECK(&mme_ue->sm, emm_state_registered)) {
return nas_security_encode(mme_ue, &message);
} else {
return ogs_nas_plain_encode(&message);
}
}

View File

@ -37,6 +37,10 @@ ogs_pkbuf_t *esm_build_modify_bearer_context_request(
mme_bearer_t *bearer, int qos_presence, int tft_presence);
ogs_pkbuf_t *esm_build_deactivate_bearer_context_request(
mme_bearer_t *bearer, ogs_nas_esm_cause_t esm_cause);
ogs_pkbuf_t *esm_build_bearer_resource_allocation_reject(
mme_bearer_t *bearer, ogs_nas_esm_cause_t esm_cause);
ogs_pkbuf_t *esm_build_bearer_resource_modification_reject(
mme_bearer_t *bearer, ogs_nas_esm_cause_t esm_cause);
#ifdef __cplusplus
}

View File

@ -29,7 +29,7 @@
#define OGS_LOG_DOMAIN __esm_log_domain
int esm_handle_pdn_connectivity_request(mme_bearer_t *bearer,
ogs_nas_pdn_connectivity_request_t *pdn_connectivity_request)
ogs_nas_pdn_connectivity_request_t *req)
{
mme_ue_t *mme_ue = NULL;
mme_sess_t *sess = NULL;
@ -41,29 +41,27 @@ int esm_handle_pdn_connectivity_request(mme_bearer_t *bearer,
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
ogs_assert(pdn_connectivity_request);
ogs_assert(req);
ogs_assert(MME_UE_HAVE_IMSI(mme_ue));
ogs_assert(SECURITY_CONTEXT_IS_VALID(mme_ue));
memcpy(&sess->request_type, &pdn_connectivity_request->request_type,
sizeof(sess->request_type));
memcpy(&sess->request_type, &req->request_type, sizeof(sess->request_type));
security_protected_required = 0;
if (pdn_connectivity_request->presencemask &
if (req->presencemask &
OGS_NAS_PDN_CONNECTIVITY_REQUEST_ESM_INFORMATION_TRANSFER_FLAG_PRESENT) {
ogs_nas_esm_information_transfer_flag_t *esm_information_transfer_flag =
&pdn_connectivity_request->esm_information_transfer_flag;
&req->esm_information_transfer_flag;
security_protected_required =
esm_information_transfer_flag->security_protected_required;
ogs_debug(" EIT(ESM information transfer)[%d]",
security_protected_required);
}
if (pdn_connectivity_request->presencemask &
if (req->presencemask &
OGS_NAS_PDN_CONNECTIVITY_REQUEST_ACCESS_POINT_NAME_PRESENT) {
sess->pdn = mme_pdn_find_by_apn(mme_ue,
pdn_connectivity_request->access_point_name.apn);
sess->pdn = mme_pdn_find_by_apn(mme_ue, req->access_point_name.apn);
if (!sess->pdn) {
/* Invalid APN */
nas_send_pdn_connectivity_reject(
@ -72,11 +70,11 @@ int esm_handle_pdn_connectivity_request(mme_bearer_t *bearer,
}
}
if (pdn_connectivity_request->presencemask &
if (req->presencemask &
OGS_NAS_PDN_CONNECTIVITY_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) {
ogs_nas_protocol_configuration_options_t
*protocol_configuration_options =
&pdn_connectivity_request->protocol_configuration_options;
&req->protocol_configuration_options;
OGS_NAS_STORE_DATA(&sess->ue_pco, protocol_configuration_options);
}
@ -106,7 +104,7 @@ int esm_handle_pdn_connectivity_request(mme_bearer_t *bearer,
}
int esm_handle_information_response(mme_sess_t *sess,
ogs_nas_esm_information_response_t *esm_information_response)
ogs_nas_esm_information_response_t *rsp)
{
mme_ue_t *mme_ue = NULL;
@ -114,17 +112,18 @@ int esm_handle_information_response(mme_sess_t *sess,
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
if (esm_information_response->presencemask &
ogs_assert(rsp);
if (rsp->presencemask &
OGS_NAS_ESM_INFORMATION_RESPONSE_ACCESS_POINT_NAME_PRESENT) {
sess->pdn = mme_pdn_find_by_apn(mme_ue,
esm_information_response->access_point_name.apn);
sess->pdn = mme_pdn_find_by_apn(mme_ue, rsp->access_point_name.apn);
}
if (esm_information_response->presencemask &
if (rsp->presencemask &
OGS_NAS_ESM_INFORMATION_RESPONSE_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT) {
ogs_nas_protocol_configuration_options_t
*protocol_configuration_options =
&esm_information_response->protocol_configuration_options;
&rsp->protocol_configuration_options;
OGS_NAS_STORE_DATA(&sess->ue_pco, protocol_configuration_options);
}
@ -150,3 +149,27 @@ int esm_handle_information_response(mme_sess_t *sess,
return OGS_OK;
}
int esm_handle_bearer_resource_allocation_request(
mme_bearer_t *bearer, ogs_nas_message_t *message)
{
ogs_assert(bearer);
nas_send_bearer_resource_allocation_reject(
bearer, ESM_CAUSE_SERVICE_OPTION_NOT_SUPPORTED);
return OGS_OK;
}
int esm_handle_bearer_resource_modification_request(
mme_bearer_t *bearer, ogs_nas_message_t *message)
{
mme_ue_t *mme_ue = NULL;
ogs_assert(bearer);
mme_ue = bearer->mme_ue;
ogs_assert(mme_ue);
mme_gtp_send_bearer_resource_command(bearer, message);
return OGS_OK;
}

View File

@ -30,6 +30,10 @@ int esm_handle_pdn_connectivity_request(mme_bearer_t *bearer,
ogs_nas_pdn_connectivity_request_t *pdn_connectivity_request);
int esm_handle_information_response(mme_sess_t *sess,
ogs_nas_esm_information_response_t *bearer_information_response);
int esm_handle_bearer_resource_allocation_request(
mme_bearer_t *bearer, ogs_nas_message_t *message);
int esm_handle_bearer_resource_modification_request(
mme_bearer_t *bearer, ogs_nas_message_t *message);
#ifdef __cplusplus
}

View File

@ -226,13 +226,25 @@ void esm_state_active(ogs_fsm_t *s, mme_event_t *e)
mme_gtp_send_update_bearer_response(bearer);
break;
case OGS_NAS_DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT:
ogs_debug("[ESM] [A] Deactivate EPS bearer "
ogs_debug("[ESM] Deactivate EPS bearer "
"context accept");
ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]",
mme_ue->imsi_bcd, sess->pti, bearer->ebi);
mme_gtp_send_delete_bearer_response(bearer);
OGS_FSM_TRAN(s, esm_state_bearer_deactivated);
break;
case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST:
ogs_debug("[ESM] Bearer resource allocation request");
ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]",
mme_ue->imsi_bcd, sess->pti, bearer->ebi);
esm_handle_bearer_resource_allocation_request(bearer, message);
break;
case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST:
ogs_debug("[ESM] Bearer resource modification request");
ogs_debug(" IMSI[%s] PTI[%d] EBI[%d]",
mme_ue->imsi_bcd, sess->pti, bearer->ebi);
esm_handle_bearer_resource_modification_request(bearer, message);
break;
default:
ogs_error("Unknown message(type:%d)",
message->esm.h.message_type);

View File

@ -2848,18 +2848,87 @@ mme_bearer_t *mme_bearer_find_or_add_by_message(
if (ebi != OGS_NAS_EPS_BEARER_IDENTITY_UNASSIGNED) {
bearer = mme_bearer_find_by_ue_ebi(mme_ue, ebi);
ogs_assert(bearer);
if (!bearer) {
ogs_error("No Bearer : EBI[%d]", ebi);
nas_send_attach_reject(mme_ue,
EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED,
ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
return NULL;
}
return bearer;
}
if (pti == OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED) {
ogs_error("Both PTI[%d] and EBI[%d] are 0", pti, ebi);
nas_send_attach_reject(mme_ue,
EMM_CAUSE_SEMANTICALLY_INCORRECT_MESSAGE,
EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED,
ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
return NULL;
}
if (message->esm.h.message_type == OGS_NAS_PDN_DISCONNECT_REQUEST) {
ogs_nas_pdn_disconnect_request_t *pdn_disconnect_request =
&message->esm.pdn_disconnect_request;
ogs_nas_linked_eps_bearer_identity_t *linked_eps_bearer_identity =
&pdn_disconnect_request->linked_eps_bearer_identity;
bearer = mme_bearer_find_by_ue_ebi(mme_ue,
linked_eps_bearer_identity->eps_bearer_identity);
if (!bearer) {
ogs_error("No Bearer : Linked-EBI[%d]",
linked_eps_bearer_identity->eps_bearer_identity);
nas_send_attach_reject(mme_ue,
EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED,
ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
return NULL;
}
} else if (message->esm.h.message_type ==
OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST) {
ogs_nas_bearer_resource_allocation_request_t
*bearer_allocation_request =
&message->esm.bearer_resource_allocation_request;
ogs_nas_linked_eps_bearer_identity_t *linked_eps_bearer_identity =
&bearer_allocation_request->linked_eps_bearer_identity;
bearer = mme_bearer_find_by_ue_ebi(mme_ue,
linked_eps_bearer_identity->eps_bearer_identity);
if (!bearer) {
ogs_error("No Bearer : Linked-EBI[%d]",
linked_eps_bearer_identity->eps_bearer_identity);
nas_send_attach_reject(mme_ue,
EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED,
ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
return NULL;
}
} else if (message->esm.h.message_type ==
OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST) {
ogs_nas_bearer_resource_modification_request_t
*bearer_modification_request =
&message->esm.bearer_resource_modification_request;
ogs_nas_linked_eps_bearer_identity_t *linked_eps_bearer_identity =
&bearer_modification_request->eps_bearer_identity_for_packet_filter;
bearer = mme_bearer_find_by_ue_ebi(mme_ue,
linked_eps_bearer_identity->eps_bearer_identity);
if (!bearer) {
ogs_error("No Bearer : Linked-EBI[%d]",
linked_eps_bearer_identity->eps_bearer_identity);
nas_send_attach_reject(mme_ue,
EMM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED,
ESM_CAUSE_PROTOCOL_ERROR_UNSPECIFIED);
return NULL;
}
}
if (bearer) {
sess = bearer->sess;
ogs_assert(sess);
sess->pti = pti;
return bearer;
}
if (message->esm.h.message_type == OGS_NAS_PDN_CONNECTIVITY_REQUEST) {
ogs_nas_pdn_connectivity_request_t *pdn_connectivity_request =
&message->esm.pdn_connectivity_request;
@ -2876,35 +2945,6 @@ mme_bearer_t *mme_bearer_find_or_add_by_message(
sess->pti = pti;
ogs_assert(sess);
} else if (message->esm.h.message_type == OGS_NAS_PDN_DISCONNECT_REQUEST) {
ogs_nas_pdn_disconnect_request_t *pdn_disconnect_request =
&message->esm.pdn_disconnect_request;
ogs_nas_linked_eps_bearer_identity_t *linked_eps_bearer_identity =
&pdn_disconnect_request->linked_eps_bearer_identity;
bearer = mme_bearer_find_by_ue_ebi(mme_ue,
linked_eps_bearer_identity->eps_bearer_identity);
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
sess->pti = pti;
return bearer;
} else if (message->esm.h.message_type ==
OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST) {
ogs_nas_bearer_resource_modification_request_t *bearer_modification_request =
&message->esm.bearer_resource_modification_request;
ogs_nas_linked_eps_bearer_identity_t *linked_eps_bearer_identity =
&bearer_modification_request->eps_bearer_identity_for_packet_filter;
bearer = mme_bearer_find_by_ue_ebi(mme_ue,
linked_eps_bearer_identity->eps_bearer_identity);
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
sess->pti = pti;
return bearer;
} else {
sess = mme_sess_find_by_pti(mme_ue, pti);
ogs_assert(sess);
@ -2912,6 +2952,7 @@ mme_bearer_t *mme_bearer_find_or_add_by_message(
bearer = mme_default_bearer_in_sess(sess);
ogs_assert(bearer);
return bearer;
}

View File

@ -440,3 +440,32 @@ void mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}
void mme_gtp_send_bearer_resource_command(
mme_bearer_t *bearer, ogs_nas_message_t *nas_message)
{
int rv;
ogs_gtp_header_t h;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp_xact_t *xact = NULL;
mme_ue_t *mme_ue = NULL;
ogs_assert(bearer);
mme_ue = bearer->mme_ue;
ogs_assert(mme_ue);
memset(&h, 0, sizeof(ogs_gtp_header_t));
h.type = OGS_GTP_BEARER_RESOURCE_COMMAND_TYPE;
h.teid = mme_ue->sgw_s11_teid;
pkbuf = mme_s11_build_bearer_resource_command(h.type, bearer, nas_message);
ogs_expect_or_return(pkbuf);
xact = ogs_gtp_xact_local_create(mme_ue->gnode, &h, pkbuf, timeout, bearer);
ogs_expect_or_return(xact);
xact->xid |= OGS_GTP_CMD_XACT_ID;
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}

View File

@ -44,6 +44,9 @@ void mme_gtp_send_create_indirect_data_forwarding_tunnel_request(
void mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
mme_ue_t *mme_ue);
void mme_gtp_send_bearer_resource_command(
mme_bearer_t *bearer, ogs_nas_message_t *nas_message);
#ifdef __cplusplus
}
#endif

View File

@ -201,9 +201,16 @@ ogs_pkbuf_t *mme_s11_build_create_session_request(
req->maximum_apn_restriction.u8 = OGS_GTP_APN_NO_RESTRICTION;
if (pdn->ambr.uplink || pdn->ambr.downlink) {
/*
* Ch 8.7. Aggregate Maximum Bit Rate(AMBR) in TS 29.274 V15.9.0
*
* AMBR is defined in clause 9.9.4.2 of 3GPP TS 24.301 [23],
* but it shall be encoded as shown in Figure 8.7-1 as
* Unsigned32 binary integer values in kbps (1000 bits per second).
*/
memset(&ambr, 0, sizeof(ogs_gtp_ambr_t));
ambr.uplink = htonl(pdn->ambr.uplink);
ambr.downlink = htonl(pdn->ambr.downlink);
ambr.uplink = htobe32(pdn->ambr.uplink / 1000);
ambr.downlink = htobe32(pdn->ambr.downlink / 1000);
req->aggregate_maximum_bit_rate.presence = 1;
req->aggregate_maximum_bit_rate.data = &ambr;
req->aggregate_maximum_bit_rate.len = sizeof(ambr);
@ -386,7 +393,7 @@ ogs_pkbuf_t *mme_s11_build_create_bearer_response(
ogs_assert(bearer);
mme_ue = bearer->mme_ue;
ogs_assert(mme_ue);
ogs_debug("[MME] Create Bearer Response");
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
@ -728,3 +735,107 @@ ogs_pkbuf_t *mme_s11_build_create_indirect_data_forwarding_tunnel_request(
gtp_message.h.type = type;
return ogs_gtp_build_msg(&gtp_message);
}
ogs_pkbuf_t *mme_s11_build_bearer_resource_command(
uint8_t type, mme_bearer_t *bearer, ogs_nas_message_t *nas_message)
{
ogs_gtp_message_t gtp_message;
ogs_gtp_bearer_resource_command_t *cmd =
&gtp_message.bearer_resource_command;
ogs_nas_bearer_resource_allocation_request_t *allocation = NULL;
ogs_nas_bearer_resource_modification_request_t *modification = NULL;
ogs_nas_eps_quality_of_service_t *qos = NULL;
ogs_nas_traffic_flow_aggregate_description_t *tad = NULL;
ogs_gtp_flow_qos_t flow_qos;
char flow_qos_buf[GTP_FLOW_QOS_LEN];
mme_ue_t *mme_ue = NULL;
mme_sess_t *sess = NULL;
mme_bearer_t *linked_bearer = NULL;
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
mme_ue = sess->mme_ue;
ogs_assert(mme_ue);
ogs_assert(nas_message);
switch (nas_message->esm.h.message_type) {
case OGS_NAS_BEARER_RESOURCE_ALLOCATION_REQUEST:
allocation = &nas_message->esm.bearer_resource_allocation_request;
qos = &allocation->required_traffic_flow_qos;
tad = &allocation->traffic_flow_aggregate;
break;
case OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST:
modification = &nas_message->esm.bearer_resource_modification_request;
if (modification->presencemask &
OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_REQUIRED_TRAFFIC_FLOW_QOS_PRESENT) {
qos = &modification->required_traffic_flow_qos;
}
tad = &modification->traffic_flow_aggregate;
break;
default:
ogs_error("Invalid NAS ESM Type[%d]",
nas_message->esm.h.message_type);
return NULL;
}
linked_bearer = mme_linked_bearer(bearer);
ogs_assert(linked_bearer);
ogs_debug("[MME] Bearer Resource Command");
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
memset(&gtp_message, 0, sizeof(ogs_gtp_message_t));
/* Linked Bearer Context : EBI */
cmd->linked_eps_bearer_id.presence = 1;
cmd->linked_eps_bearer_id.u8 = bearer->ebi;
/* Procedure Transaction ID(PTI) */
cmd->procedure_transaction_id.presence = 1;
cmd->procedure_transaction_id.u8 = sess->pti;
/* Flow Quality of Service(QoS) */
if (qos) {
memset(&flow_qos, 0, sizeof(flow_qos));
flow_qos.qci = qos->qci;
/* Octet 4
*
* In UE to network direction:
* 00000000 Subscribed maximum bit rate
*
* In network to UE direction:
* 00000000 Reserved
*/
flow_qos.ul_mbr = qos->ul_mbr == 0 ? bearer->qos.mbr.uplink :
ogs_gtp_qos_to_bps(
qos->ul_mbr, qos->ul_mbr_extended, qos->ul_mbr_extended2);
flow_qos.dl_mbr = qos->dl_mbr == 0 ? bearer->qos.mbr.downlink :
ogs_gtp_qos_to_bps(
qos->dl_mbr, qos->dl_mbr_extended, qos->dl_mbr_extended2);
flow_qos.ul_gbr = qos->ul_gbr == 0 ? bearer->qos.gbr.uplink :
ogs_gtp_qos_to_bps(
qos->ul_gbr, qos->ul_gbr_extended, qos->ul_gbr_extended2);
flow_qos.dl_gbr = qos->dl_gbr == 0 ? bearer->qos.gbr.downlink :
ogs_gtp_qos_to_bps(
qos->dl_gbr, qos->dl_gbr_extended, qos->dl_gbr_extended2);
ogs_gtp_build_flow_qos(
&cmd->flow_quality_of_service,
&flow_qos, flow_qos_buf, GTP_FLOW_QOS_LEN);
cmd->flow_quality_of_service.presence = 1;
}
/* Traffic Aggregate Description(TAD) */
cmd->traffic_aggregate_description.presence = 1;
cmd->traffic_aggregate_description.data = tad->buffer;
cmd->traffic_aggregate_description.len = tad->length;
gtp_message.h.type = type;
return ogs_gtp_build_msg(&gtp_message);
}

View File

@ -41,6 +41,9 @@ ogs_pkbuf_t *mme_s11_build_downlink_data_notification_ack(uint8_t type);
ogs_pkbuf_t *mme_s11_build_create_indirect_data_forwarding_tunnel_request(
uint8_t type, mme_ue_t *mme_ue);
ogs_pkbuf_t *mme_s11_build_bearer_resource_command(
uint8_t type, mme_bearer_t *bearer, ogs_nas_message_t *nas_message);
#ifdef __cplusplus
}
#endif

View File

@ -506,6 +506,13 @@ void mme_s11_handle_update_bearer_request(
} else {
ogs_warn("[IGNORE] Update Bearer Request : "
"Both QoS and TFT is NULL");
if (xact->xid & OGS_GTP_CMD_XACT_ID) {
/* MME recieved Bearer resource modification request */
nas_send_bearer_resource_modification_reject(
bearer, ESM_CAUSE_SERVICE_OPTION_NOT_SUPPORTED);
}
mme_gtp_send_update_bearer_response(bearer);
}
} else {
@ -791,3 +798,39 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
rv = mme_ue_clear_indirect_tunnel(mme_ue);
ogs_expect(rv == OGS_OK);
}
void mme_s11_handle_bearer_resource_failure_indication(
ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp_bearer_resource_failure_indication_t *ind)
{
int rv;
uint8_t cause_value = 0;
mme_bearer_t *bearer = NULL;
ogs_assert(xact);
bearer = xact->data;
ogs_assert(ind);
ogs_debug("[MME] Bearer Resource Failure Indication");
rv = ogs_gtp_xact_commit(xact);
ogs_expect_or_return(rv == OGS_OK);
if (ind->cause.presence) {
ogs_gtp_cause_t *cause = ind->cause.data;
ogs_assert(cause);
cause_value = cause->value;
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED)
ogs_warn("GTP Failed [CAUSE:%d] - Ignored", cause_value);
} else {
ogs_error("No Cause");
}
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
mme_ue->mme_s11_teid, mme_ue->sgw_s11_teid);
nas_send_bearer_resource_modification_reject(
bearer, ESM_CAUSE_SERVICE_OPTION_NOT_SUPPORTED);
}

View File

@ -58,6 +58,10 @@ void mme_s11_handle_delete_indirect_data_forwarding_tunnel_response(
ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp_delete_indirect_data_forwarding_tunnel_response_t *rsp);
void mme_s11_handle_bearer_resource_failure_indication(
ogs_gtp_xact_t *xact, mme_ue_t *mme_ue,
ogs_gtp_bearer_resource_failure_indication_t *ind);
#ifdef __cplusplus
}
#endif

View File

@ -589,6 +589,11 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
xact, mme_ue,
&gtp_message.delete_indirect_data_forwarding_tunnel_response);
break;
case OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE:
mme_s11_handle_bearer_resource_failure_indication(
xact, mme_ue,
&gtp_message.bearer_resource_failure_indication);
break;
default:
ogs_warn("Not implmeneted(type:%d)", gtp_message.h.type);
break;

View File

@ -425,6 +425,42 @@ void nas_send_deactivate_bearer_context_request(mme_bearer_t *bearer)
ogs_expect(rv == OGS_OK);
}
void nas_send_bearer_resource_allocation_reject(
mme_bearer_t *bearer, ogs_nas_esm_cause_t esm_cause)
{
int rv;
mme_ue_t *mme_ue;
ogs_pkbuf_t *esmbuf = NULL;
ogs_assert(bearer);
mme_ue = bearer->mme_ue;
ogs_assert(bearer);
esmbuf = esm_build_bearer_resource_allocation_reject(bearer, esm_cause);
ogs_expect_or_return(esmbuf);
rv = nas_send_to_downlink_nas_transport(mme_ue, esmbuf);
ogs_expect(rv == OGS_OK);
}
void nas_send_bearer_resource_modification_reject(
mme_bearer_t *bearer, ogs_nas_esm_cause_t esm_cause)
{
int rv;
mme_ue_t *mme_ue;
ogs_pkbuf_t *esmbuf = NULL;
ogs_assert(bearer);
mme_ue = bearer->mme_ue;
ogs_assert(bearer);
esmbuf = esm_build_bearer_resource_modification_reject(bearer, esm_cause);
ogs_expect_or_return(esmbuf);
rv = nas_send_to_downlink_nas_transport(mme_ue, esmbuf);
ogs_expect(rv == OGS_OK);
}
void nas_send_tau_accept(
mme_ue_t *mme_ue, S1AP_ProcedureCode_t procedureCode)
{

View File

@ -54,6 +54,10 @@ void nas_send_activate_all_dedicated_bearers(mme_bearer_t *default_bearer);
void nas_send_modify_bearer_context_request(
mme_bearer_t *bearer, int qos_presence, int tft_presence);
void nas_send_deactivate_bearer_context_request(mme_bearer_t *bearer);
void nas_send_bearer_resource_allocation_reject(
mme_bearer_t *bearer, ogs_nas_esm_cause_t esm_cause);
void nas_send_bearer_resource_modification_reject(
mme_bearer_t *bearer, ogs_nas_esm_cause_t esm_cause);
void nas_send_tau_accept(mme_ue_t *mme_ue, S1AP_ProcedureCode_t procedureCode);
void nas_send_tau_reject(mme_ue_t *mme_ue, ogs_nas_esm_cause_t emm_cause);

View File

@ -1176,16 +1176,12 @@ void pgw_pf_remove_all(pgw_bearer_t *bearer)
pgw_pf_t *pgw_pf_find_by_id(pgw_bearer_t *bearer, uint8_t id)
{
pgw_pf_t *pf = NULL;
pf = pgw_pf_first(bearer);
while (pf) {
if (pf->identifier == id)
return pf;
pf = pgw_pf_next(pf);
ogs_list_for_each(&bearer->pf_list, pf) {
if (pf->identifier == id) return pf;
}
return OGS_OK;
return NULL;
}
pgw_pf_t *pgw_pf_first(pgw_bearer_t *bearer)

View File

@ -220,7 +220,9 @@ static void bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message)
h.teid = sess->sgw_s5c_teid;
pkbuf = pgw_s5c_build_update_bearer_request(
h.type, bearer, qos_presence, tft_presence);
h.type, bearer,
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED,
tft_presence, NULL, qos_presence);
ogs_expect_or_return(pkbuf);
}
@ -238,7 +240,8 @@ static void bearer_binding(pgw_sess_t *sess, ogs_diam_gx_message_t *gx_message)
h.type = OGS_GTP_DELETE_BEARER_REQUEST_TYPE;
h.teid = sess->sgw_s5c_teid;
pkbuf = pgw_s5c_build_delete_bearer_request(h.type, bearer);
pkbuf = pgw_s5c_build_delete_bearer_request(h.type, bearer,
OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED);
ogs_expect_or_return(pkbuf);
xact = ogs_gtp_xact_local_create(

View File

@ -358,15 +358,15 @@ 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,
int qos_presence, int tft_presence)
uint8_t type, pgw_bearer_t *bearer, uint8_t pti,
int tft_presence, ogs_gtp_tft_t *new_tft, int qos_presence)
{
pgw_sess_t *sess = NULL;
pgw_bearer_t *linked_bearer = NULL;
ogs_gtp_message_t gtp_message;
ogs_gtp_update_bearer_request_t *req = NULL;
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;
@ -375,8 +375,6 @@ ogs_pkbuf_t *pgw_s5c_build_update_bearer_request(
ogs_assert(bearer);
sess = bearer->sess;
ogs_assert(sess);
linked_bearer = pgw_default_bearer_in_sess(sess);
ogs_assert(linked_bearer);
ogs_debug("[PGW] Update Bearer Request");
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
@ -389,6 +387,28 @@ ogs_pkbuf_t *pgw_s5c_build_update_bearer_request(
req->bearer_contexts.eps_bearer_id.presence = 1;
req->bearer_contexts.eps_bearer_id.u8 = bearer->ebi;
if (sess->pdn.ambr.uplink || sess->pdn.ambr.downlink) {
/*
* Ch 8.7. Aggregate Maximum Bit Rate(AMBR) in TS 29.274 V15.9.0
*
* AMBR is defined in clause 9.9.4.2 of 3GPP TS 24.301 [23],
* but it shall be encoded as shown in Figure 8.7-1 as
* Unsigned32 binary integer values in kbps (1000 bits per second).
*/
memset(&ambr, 0, sizeof(ogs_gtp_ambr_t));
ambr.uplink = htobe32(sess->pdn.ambr.uplink / 1000);
ambr.downlink = htobe32(sess->pdn.ambr.downlink / 1000);
req->aggregate_maximum_bit_rate.presence = 1;
req->aggregate_maximum_bit_rate.data = &ambr;
req->aggregate_maximum_bit_rate.len = sizeof(ambr);
}
/* PTI */
if (pti) {
req->procedure_transaction_id.presence = 1;
req->procedure_transaction_id.u8 = pti;
}
/* Bearer QoS */
if (qos_presence == 1) {
memset(&bearer_qos, 0, sizeof(bearer_qos));
@ -410,10 +430,16 @@ ogs_pkbuf_t *pgw_s5c_build_update_bearer_request(
/* Bearer TFT */
if (tft_presence == 1) {
encode_traffic_flow_template(&tft, bearer);
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);
}
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;
@ -421,7 +447,7 @@ ogs_pkbuf_t *pgw_s5c_build_update_bearer_request(
}
ogs_pkbuf_t *pgw_s5c_build_delete_bearer_request(
uint8_t type, pgw_bearer_t *bearer)
uint8_t type, pgw_bearer_t *bearer, uint8_t pti)
{
pgw_sess_t *sess = NULL;
pgw_bearer_t *linked_bearer = NULL;
@ -451,6 +477,11 @@ ogs_pkbuf_t *pgw_s5c_build_delete_bearer_request(
req->eps_bearer_ids.u8 = bearer->ebi;
}
if (pti) {
req->procedure_transaction_id.presence = 1;
req->procedure_transaction_id.u8 = pti;
}
gtp_message.h.type = type;
return ogs_gtp_build_msg(&gtp_message);
}

View File

@ -37,10 +37,10 @@ ogs_pkbuf_t *pgw_s5c_build_delete_session_response(
ogs_pkbuf_t *pgw_s5c_build_create_bearer_request(
uint8_t type, pgw_bearer_t *bearer);
ogs_pkbuf_t *pgw_s5c_build_update_bearer_request(
uint8_t type, pgw_bearer_t *bearer,
int qos_presence, int tft_presence);
uint8_t type, pgw_bearer_t *bearer, uint8_t pti,
int tft_presence, ogs_gtp_tft_t *new_tft, int qos_presence);
ogs_pkbuf_t *pgw_s5c_build_delete_bearer_request(
uint8_t type, pgw_bearer_t *bearer);
uint8_t type, pgw_bearer_t *bearer, uint8_t pti);
#ifdef __cplusplus
}
#endif

View File

@ -21,8 +21,11 @@
#include "pgw-context.h"
#include "pgw-gtp-path.h"
#include "pgw-fd-path.h"
#include "pgw-s5c-build.h"
#include "pgw-s5c-handler.h"
#include "ipfw/ipfw2.h"
void pgw_s5c_handle_create_session_request(
pgw_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_pkbuf_t *gtpbuf, ogs_gtp_create_session_request_t *req)
@ -134,9 +137,16 @@ void pgw_s5c_handle_create_session_request(
/* Set AMBR if available */
if (req->aggregate_maximum_bit_rate.presence) {
/*
* Ch 8.7. Aggregate Maximum Bit Rate(AMBR) in TS 29.274 V15.9.0
*
* AMBR is defined in clause 9.9.4.2 of 3GPP TS 24.301 [23],
* but it shall be encoded as shown in Figure 8.7-1 as
* Unsigned32 binary integer values in kbps (1000 bits per second).
*/
ambr = req->aggregate_maximum_bit_rate.data;
sess->pdn.ambr.downlink = ntohl(ambr->downlink);
sess->pdn.ambr.uplink = ntohl(ambr->uplink);
sess->pdn.ambr.downlink = be32toh(ambr->downlink) * 1000;
sess->pdn.ambr.uplink = be32toh(ambr->uplink) * 1000;
}
/* Set User Location Information */
@ -209,7 +219,7 @@ void pgw_s5c_handle_create_bearer_response(
return;
}
/* Correlate with PGW-S%U-TEID */
/* Correlate with PGW-S5U-TEID */
pgw_s5u_teid = req->bearer_contexts.s5_s8_u_pgw_f_teid.data;
ogs_assert(pgw_s5u_teid);
@ -309,3 +319,239 @@ void pgw_s5c_handle_delete_bearer_response(
pgw_bearer_remove(bearer);
}
static int reconfigure_packet_filter(pgw_pf_t *pf, ogs_gtp_tft_t *tft, int i)
{
int j;
for (j = 0; j < tft->pf[i].num_of_component; j++) {
switch(tft->pf[i].component[j].type) {
case GTP_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE:
pf->rule.proto = tft->pf[i].component[j].proto;
break;
case GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE:
pf->rule.ipv4_remote = 1;
pf->rule.ip.remote.addr[0] = tft->pf[i].component[j].ipv4.addr;
pf->rule.ip.remote.mask[0] = tft->pf[i].component[j].ipv4.mask;
break;
case GTP_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE:
pf->rule.ipv4_local = 1;
pf->rule.ip.local.addr[0] = tft->pf[i].component[j].ipv4.addr;
pf->rule.ip.local.mask[0] = tft->pf[i].component[j].ipv4.mask;
break;
case GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE:
pf->rule.ipv6_remote = 1;
memcpy(pf->rule.ip.remote.addr,
tft->pf[i].component[j].ipv6_mask.addr,
sizeof(pf->rule.ip.remote.addr));
memcpy(pf->rule.ip.remote.mask,
tft->pf[i].component[j].ipv6_mask.mask,
sizeof(pf->rule.ip.remote.mask));
break;
case GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE:
pf->rule.ipv6_remote = 1;
memcpy(pf->rule.ip.remote.addr,
tft->pf[i].component[j].ipv6_mask.addr,
sizeof(pf->rule.ip.remote.addr));
n2mask((struct in6_addr *)pf->rule.ip.remote.mask,
tft->pf[i].component[j].ipv6.prefixlen);
break;
case GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_TYPE:
pf->rule.ipv6_local = 1;
memcpy(pf->rule.ip.local.addr,
tft->pf[i].component[j].ipv6_mask.addr,
sizeof(pf->rule.ip.local.addr));
memcpy(pf->rule.ip.local.mask,
tft->pf[i].component[j].ipv6_mask.mask,
sizeof(pf->rule.ip.local.mask));
break;
case GTP_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE:
pf->rule.ipv6_local = 1;
memcpy(pf->rule.ip.local.addr,
tft->pf[i].component[j].ipv6_mask.addr,
sizeof(pf->rule.ip.local.addr));
n2mask((struct in6_addr *)pf->rule.ip.local.mask,
tft->pf[i].component[j].ipv6.prefixlen);
break;
case GTP_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE:
pf->rule.port.local.low = pf->rule.port.local.high =
tft->pf[i].component[j].port.low;
break;
case GTP_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE:
pf->rule.port.remote.low = pf->rule.port.remote.high =
tft->pf[i].component[j].port.low;
break;
case GTP_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE:
pf->rule.port.local.low = tft->pf[i].component[j].port.low;
pf->rule.port.local.high = tft->pf[i].component[j].port.high;
break;
case GTP_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE:
pf->rule.port.remote.low = tft->pf[i].component[j].port.low;
pf->rule.port.remote.high = tft->pf[i].component[j].port.high;
break;
default:
ogs_error("Unknown Packet Filter Type(%d)",
tft->pf[i].component[j].type);
return OGS_ERROR;
}
}
return j;
}
void pgw_s5c_handle_bearer_resource_command(
pgw_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp_bearer_resource_command_t *cmd)
{
int rv;
uint8_t cause_value = 0;
ogs_gtp_header_t h;
ogs_pkbuf_t *pkbuf = NULL;
pgw_bearer_t *bearer = NULL;
int16_t decoded;
ogs_gtp_tft_t tft;
int tft_presence = 0;
int qos_presence = 0;
ogs_assert(xact);
ogs_assert(sess);
ogs_assert(cmd);
ogs_debug("[PGW] Bearer Resource Command");
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
if (cmd->linked_eps_bearer_id.presence == 0) {
ogs_error("No Linked EPS Bearer ID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
} else {
bearer = pgw_bearer_find_by_ebi(
sess, cmd->linked_eps_bearer_id.u8);
if (!bearer) {
ogs_error("No Context for Linked EPS Bearer ID[%d]",
cmd->linked_eps_bearer_id.u8);
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
}
if (cmd->procedure_transaction_id.presence == 0) {
ogs_error("No PTI");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cmd->traffic_aggregate_description.presence == 0) {
ogs_error("No Traffic aggregate description(TAD)");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0,
OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value);
return;
}
ogs_assert(bearer);
decoded = ogs_gtp_parse_tft(&tft, &cmd->traffic_aggregate_description);
ogs_assert(cmd->traffic_aggregate_description.len == decoded);
if (tft.code == OGS_GTP_TFT_CODE_NO_TFT_OPERATION) {
/* No operation */
} else if (tft.code ==
OGS_GTP_TFT_CODE_REPLACE_PACKET_FILTERS_IN_EXISTING) {
int i;
for (i = 0; i < tft.num_of_packet_filter; i++) {
int num_of_comp = 0;
pgw_pf_t *pf = NULL;
pf = pgw_pf_find_by_id(bearer, tft.pf[i].identifier+1);
if (pf) {
num_of_comp = reconfigure_packet_filter(pf, &tft, i);
if (num_of_comp < 0) {
ogs_gtp_send_error_message(
xact, sess ? sess->sgw_s5c_teid : 0,
OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE,
OGS_GTP_CAUSE_SEMANTIC_ERROR_IN_THE_TAD_OPERATION);
return;
}
}
if (num_of_comp > 0) tft_presence = 1;
}
} else if (tft.code ==
OGS_GTP_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT) {
int i;
for (i = 0; i < tft.num_of_packet_filter; i++) {
int num_of_comp = 0;
pgw_pf_t *pf = NULL;
pf = pgw_pf_find_by_id(bearer, tft.pf[i].identifier+1);
if (!pf)
pf = pgw_pf_add(bearer, tft.pf[i].precedence);
ogs_assert(pf);
num_of_comp = reconfigure_packet_filter(pf, &tft, i);
if (num_of_comp < 0) {
ogs_gtp_send_error_message(
xact, sess ? sess->sgw_s5c_teid : 0,
OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE,
OGS_GTP_CAUSE_SEMANTIC_ERROR_IN_THE_TAD_OPERATION);
return;
}
if (num_of_comp > 0) tft_presence = 1;
}
} else if (tft.code ==
OGS_GTP_TFT_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING) {
/* TODO */
ogs_gtp_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0,
OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE,
OGS_GTP_CAUSE_SERVICE_NOT_SUPPORTED);
return;
}
if (cmd->flow_quality_of_service.presence) {
ogs_gtp_flow_qos_t flow_qos;
decoded = ogs_gtp_parse_flow_qos(
&flow_qos, &cmd->flow_quality_of_service);
ogs_assert(cmd->flow_quality_of_service.len == decoded);
bearer->qos.mbr.uplink = flow_qos.ul_mbr;
bearer->qos.mbr.downlink = flow_qos.dl_mbr;
bearer->qos.gbr.uplink = flow_qos.ul_gbr;
bearer->qos.gbr.downlink = flow_qos.dl_gbr;
qos_presence = 1;
}
if (tft_presence == 0 && qos_presence == 0) {
/* No modification */
ogs_gtp_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0,
OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE,
OGS_GTP_CAUSE_SERVICE_NOT_SUPPORTED);
return;
}
memset(&h, 0, sizeof(ogs_gtp_header_t));
h.type = OGS_GTP_UPDATE_BEARER_REQUEST_TYPE;
h.teid = sess->sgw_s5c_teid;
pkbuf = pgw_s5c_build_update_bearer_request(
h.type, bearer, cmd->procedure_transaction_id.u8,
tft_presence, &tft, qos_presence);
ogs_expect_or_return(pkbuf);
rv = ogs_gtp_xact_update_tx(xact, &h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
}

View File

@ -41,6 +41,9 @@ void pgw_s5c_handle_update_bearer_response(
void pgw_s5c_handle_delete_bearer_response(
pgw_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp_delete_bearer_response_t *req);
void pgw_s5c_handle_bearer_resource_command(
pgw_sess_t *sess, ogs_gtp_xact_t *xact,
ogs_gtp_bearer_resource_command_t *cmd);
#ifdef __cplusplus
}

View File

@ -161,6 +161,11 @@ void pgw_state_operational(ogs_fsm_t *s, pgw_event_t *e)
sess, xact, &message->delete_bearer_response);
ogs_pkbuf_free(copybuf);
break;
case OGS_GTP_BEARER_RESOURCE_COMMAND_TYPE:
pgw_s5c_handle_bearer_resource_command(
sess, xact, &message->bearer_resource_command);
ogs_pkbuf_free(copybuf);
break;
default:
ogs_warn("Not implmeneted(type:%d)", message->h.type);
ogs_pkbuf_free(copybuf);

View File

@ -1210,3 +1210,77 @@ void sgw_s11_handle_delete_indirect_data_forwarding_tunnel_request(
rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK);
}
void sgw_s11_handle_bearer_resource_command(ogs_gtp_xact_t *s11_xact,
sgw_ue_t *sgw_ue, ogs_gtp_message_t *message)
{
int rv;
ogs_pkbuf_t *pkbuf = NULL;
ogs_gtp_bearer_resource_command_t *cmd = NULL;
uint8_t cause_value = 0;
ogs_gtp_xact_t *s5c_xact = NULL;
sgw_sess_t *sess = NULL;
ogs_assert(s11_xact);
ogs_assert(message);
ogs_debug("[SGW] Bearer Resource Command");
cmd = &message->bearer_resource_command;
cause_value = OGS_GTP_CAUSE_REQUEST_ACCEPTED;
if (!sgw_ue) {
ogs_warn("No Context");
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (cmd->linked_eps_bearer_id.presence == 0) {
ogs_error("No Linked EPS Bearer ID");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
} else {
sess = sgw_sess_find_by_ebi(sgw_ue, cmd->linked_eps_bearer_id.u8);
if (!sess) {
ogs_error("No Context for Linked EPS Bearer ID[%d]",
cmd->linked_eps_bearer_id.u8);
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
}
if (cmd->procedure_transaction_id.presence == 0) {
ogs_error("No PTI");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cmd->traffic_aggregate_description.presence == 0) {
ogs_error("No Traffic aggregate description(TAD)");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
if (cause_value != OGS_GTP_CAUSE_REQUEST_ACCEPTED) {
ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0,
OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value);
return;
}
ogs_assert(sess);
ogs_debug(" MME_S11_TEID[%d] SGW_S11_TEID[%d]",
sgw_ue->mme_s11_teid, sgw_ue->sgw_s11_teid);
ogs_debug(" SGW_S5C_TEID[0x%x] PGW_S5C_TEID[0x%x]",
sess->sgw_s5c_teid, sess->pgw_s5c_teid);
message->h.type = OGS_GTP_BEARER_RESOURCE_COMMAND_TYPE;
message->h.teid = sess->pgw_s5c_teid;
pkbuf = ogs_gtp_build_msg(message);
ogs_expect_or_return(pkbuf);
s5c_xact = ogs_gtp_xact_local_create(
sess->gnode, &message->h, pkbuf, timeout, sess);
ogs_expect_or_return(s5c_xact);
ogs_gtp_xact_associate(s11_xact, s5c_xact);
rv = ogs_gtp_xact_commit(s5c_xact);
ogs_expect(rv == OGS_OK);
}

View File

@ -27,17 +27,17 @@ extern "C" {
#endif
void sgw_s11_handle_create_session_request(ogs_gtp_xact_t *s11_xact,
sgw_ue_t *sgw_ue, ogs_gtp_message_t *gtp_message);
sgw_ue_t *sgw_ue, ogs_gtp_message_t *message);
void sgw_s11_handle_modify_bearer_request(ogs_gtp_xact_t *s11_xact,
sgw_ue_t *sgw_ue, ogs_gtp_modify_bearer_request_t *req);
void sgw_s11_handle_delete_session_request(ogs_gtp_xact_t *s11_xact,
sgw_ue_t *sgw_ue, ogs_gtp_message_t *gtp_message);
sgw_ue_t *sgw_ue, ogs_gtp_message_t *message);
void sgw_s11_handle_create_bearer_response(ogs_gtp_xact_t *s11_xact,
sgw_ue_t *sgw_ue, ogs_gtp_message_t *gtp_message);
sgw_ue_t *sgw_ue, ogs_gtp_message_t *message);
void sgw_s11_handle_update_bearer_response(ogs_gtp_xact_t *s11_xact,
sgw_ue_t *sgw_ue, ogs_gtp_message_t *gtp_message);
sgw_ue_t *sgw_ue, ogs_gtp_message_t *message);
void sgw_s11_handle_delete_bearer_response(ogs_gtp_xact_t *s11_xact,
sgw_ue_t *sgw_ue, ogs_gtp_message_t *gtp_message);
sgw_ue_t *sgw_ue, ogs_gtp_message_t *message);
void sgw_s11_handle_release_access_bearers_request(
ogs_gtp_xact_t *s11_xact, sgw_ue_t *sgw_ue,
@ -53,6 +53,9 @@ void sgw_s11_handle_create_indirect_data_forwarding_tunnel_request(
void sgw_s11_handle_delete_indirect_data_forwarding_tunnel_request(
ogs_gtp_xact_t *s11_xact, sgw_ue_t *sgw_ue);
void sgw_s11_handle_bearer_resource_command(ogs_gtp_xact_t *s11_xact,
sgw_ue_t *sgw_ue, ogs_gtp_message_t *message);
#ifdef __cplusplus
}
#endif

View File

@ -450,11 +450,17 @@ void sgw_s5c_handle_update_bearer_request(ogs_gtp_xact_t *s5c_xact,
pkbuf = ogs_gtp_build_msg(message);
ogs_expect_or_return(pkbuf);
s11_xact = ogs_gtp_xact_local_create(
sgw_ue->gnode, &message->h, pkbuf, timeout, sess);
ogs_expect_or_return(s11_xact);
s11_xact = s5c_xact->assoc_xact;
if (!s11_xact) {
s11_xact = ogs_gtp_xact_local_create(
sgw_ue->gnode, &message->h, pkbuf, timeout, sess);
ogs_expect_or_return(s11_xact);
ogs_gtp_xact_associate(s5c_xact, s11_xact);
ogs_gtp_xact_associate(s5c_xact, s11_xact);
} else {
rv = ogs_gtp_xact_update_tx(s11_xact, &message->h, pkbuf);
ogs_expect_or_return(rv == OGS_OK);
}
rv = ogs_gtp_xact_commit(s11_xact);
ogs_expect(rv == OGS_OK);
@ -521,3 +527,43 @@ void sgw_s5c_handle_delete_bearer_request(ogs_gtp_xact_t *s5c_xact,
ogs_expect(rv == OGS_OK);
}
void sgw_s5c_handle_bearer_resource_failure_indication(ogs_gtp_xact_t *s5c_xact,
sgw_sess_t *sess, ogs_gtp_message_t *message)
{
uint8_t cause_value = 0;
ogs_gtp_xact_t *s11_xact = NULL;
ogs_gtp_bearer_resource_failure_indication_t *ind = NULL;
sgw_ue_t *sgw_ue = NULL;
ogs_assert(s5c_xact);
s11_xact = s5c_xact->assoc_xact;
ogs_assert(s11_xact);
ogs_assert(message);
ogs_debug("[SGW] Bearer Resource Failure Indication");
ind = &message->bearer_resource_failure_indication;
if (!sess) {
ogs_warn("No Context");
cause_value = OGS_GTP_CAUSE_CONTEXT_NOT_FOUND;
}
if (ind->cause.presence) {
ogs_gtp_cause_t *cause = ind->cause.data;
ogs_assert(cause);
cause_value = cause->value;
} else {
ogs_error("No Cause");
cause_value = OGS_GTP_CAUSE_MANDATORY_IE_MISSING;
}
sgw_ue = sess->sgw_ue;
ogs_assert(sgw_ue);
ogs_gtp_send_error_message(s11_xact, sgw_ue ? sgw_ue->mme_s11_teid : 0,
OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE, cause_value);
}

View File

@ -36,6 +36,8 @@ void sgw_s5c_handle_update_bearer_request(ogs_gtp_xact_t *s5c_xact,
sgw_sess_t *sess, ogs_gtp_message_t *gtp_message);
void sgw_s5c_handle_delete_bearer_request(ogs_gtp_xact_t *s5c_xact,
sgw_sess_t *sess, ogs_gtp_message_t *gtp_message);
void sgw_s5c_handle_bearer_resource_failure_indication(ogs_gtp_xact_t *s5c_xact,
sgw_sess_t *sess, ogs_gtp_message_t *message);
#ifdef __cplusplus
}

View File

@ -140,6 +140,9 @@ void sgw_state_operational(ogs_fsm_t *s, sgw_event_t *e)
sgw_s11_handle_delete_indirect_data_forwarding_tunnel_request(
xact, sgw_ue);
break;
case OGS_GTP_BEARER_RESOURCE_COMMAND_TYPE:
sgw_s11_handle_bearer_resource_command(xact, sgw_ue, &message);
break;
default:
ogs_warn("Not implmeneted(type:%d)", message.h.type);
break;
@ -194,6 +197,10 @@ void sgw_state_operational(ogs_fsm_t *s, sgw_event_t *e)
sgw_s5c_handle_delete_bearer_request(xact, sess,
&message);
break;
case OGS_GTP_BEARER_RESOURCE_FAILURE_INDICATION_TYPE:
sgw_s5c_handle_bearer_resource_failure_indication(xact, sess,
&message);
break;
default:
ogs_warn("Not implmeneted(type:%d)", message.h.type);
break;

View File

@ -86,6 +86,7 @@ void test_app_init(void)
ogs_log_install_domain(&__ogs_s1ap_domain, "s1ap", OGS_LOG_ERROR);
ogs_log_install_domain(&__ogs_diam_domain, "diam", OGS_LOG_ERROR);
ogs_log_install_domain(&__ogs_dbi_domain, "dbi", OGS_LOG_ERROR);
ogs_log_install_domain(&__ogs_nas_domain, "nas", OGS_LOG_ERROR);
ogs_assert(ogs_mongoc_init(ogs_config()->db_uri) == OGS_OK);
}

View File

@ -2144,7 +2144,8 @@ int tests1ap_build_e_rab_modify_response(ogs_pkbuf_t **pkbuf, int i)
const char *payload[TESTS1AP_MAX_MESSAGE] = {
"2006"
"001b000003000040 0480000001000840 020001001f400600 002500010e",
"",
"2006"
"001b000003000040 0480000001000840 020001001f400600 002500010e",
"",
"",
@ -2158,7 +2159,7 @@ int tests1ap_build_e_rab_modify_response(ogs_pkbuf_t **pkbuf, int i)
};
uint16_t len[TESTS1AP_MAX_MESSAGE] = {
31,
0,
31,
0,
0,
@ -2319,8 +2320,12 @@ int tests1ap_build_modify_bearer_accept(
"000d"
"4035000005000000 0480000001000800 020001001a000a09 27a5c0d564067200"
"ca006440080064f0 430020a000004340 060064f043020a",
"",
"",
"000d"
"4035000005000000 0480000001000800 020001001a000a09 27a6746cea097204"
"ca006440080064f0 430020a000004340 060064f043020a",
"000d"
"4035000005000000 0480000001000800 020001001a000a09 2726b727fe0a7205"
"ca006440080064f0 430020a000004340 060064f043020a",
"",
"",
@ -2336,8 +2341,8 @@ int tests1ap_build_modify_bearer_accept(
};
uint16_t len[TESTS1AP_MAX_MESSAGE] = {
57,
0,
0,
57,
57,
0,
0,
@ -2405,6 +2410,321 @@ int tests1ap_build_deactivate_bearer_accept(
return OGS_OK;
}
int tests1ap_build_bearer_resource_allocation_request(
ogs_pkbuf_t **pkbuf, int i)
{
const char *payload[TESTS1AP_MAX_MESSAGE] = {
"000d"
"403f000005000000 0200010008000200 01001a00161517fe b2b150070203d406"
"04212001000501ff ffffff0064400800 2143650003039000 4340060021436509"
"29",
"",
"",
"",
"",
"",
};
uint16_t len[TESTS1AP_MAX_MESSAGE] = {
67,
0,
0,
0,
0,
0,
};
char hexbuf[OGS_MAX_SDU_LEN];
*pkbuf = ogs_pkbuf_alloc(NULL, OGS_MAX_SDU_LEN);
ogs_pkbuf_put_data(*pkbuf,
OGS_HEX(payload[i], strlen(payload[i]), hexbuf), len[i]);
return OGS_OK;
}
static void build_bearer_resource_modification_request(ogs_pkbuf_t **pkbuf,
uint8_t pti, uint32_t mac, uint8_t seq, uint8_t ebi,
uint8_t tft_code, uint8_t qci,
uint8_t ul_mbr, uint8_t dl_mbr, uint8_t ul_gbr, uint8_t dl_gbr)
{
int rv;
ogs_pkbuf_t *emmbuf = NULL;
ogs_nas_message_t message;
ogs_nas_bearer_resource_modification_request_t
*req = &message.esm.bearer_resource_modification_request;
ogs_nas_traffic_flow_aggregate_description_t *tad =
&req->traffic_flow_aggregate;
ogs_nas_eps_quality_of_service_t *qos = &req->required_traffic_flow_qos;
ogs_gtp_tft_t tft;
ogs_tlv_octet_t octet;
int len;
char tft_buf[OGS_GTP_MAX_TRAFFIC_FLOW_TEMPLATE];
ogs_ipsubnet_t ipsubnet;
memset(&message, 0, sizeof(message));
message.esm.h.eps_bearer_identity = 0;
message.esm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_ESM;
message.esm.h.procedure_transaction_identity = pti;
message.esm.h.message_type = OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST;
req->eps_bearer_identity_for_packet_filter.eps_bearer_identity = ebi;
memset(&tft, 0, sizeof tft);
tft.code = tft_code;
if (tft.code == OGS_GTP_TFT_CODE_REPLACE_PACKET_FILTERS_IN_EXISTING) {
tft.num_of_packet_filter = 1;
tft.pf[0].direction = 1;
tft.pf[0].identifier = 0;
tft.pf[0].precedence = 0x0f;
tft.pf[0].length = 9;
tft.pf[0].component[0].type =
GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE;
rv = ogs_ipsubnet(&ipsubnet, "201.20.2.5", NULL);
ogs_assert(rv == OGS_OK);
tft.pf[0].component[0].ipv4.addr = ipsubnet.sub[0];
tft.pf[0].component[0].ipv4.mask = ipsubnet.mask[0];
tft.pf[0].num_of_component = 1;
} else if (tft.code ==
OGS_GTP_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT) {
tft.num_of_packet_filter = 1;
tft.pf[0].direction = 1;
tft.pf[0].identifier = 4;
tft.pf[0].precedence = 0x0f;
rv = ogs_ipsubnet(&ipsubnet, "cafe::9", "120");
ogs_assert(rv == OGS_OK);
#if 1
tft.pf[0].length = 18;
tft.pf[0].component[0].type =
GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE;
memcpy(tft.pf[0].component[0].ipv6.addr, ipsubnet.sub,
sizeof(tft.pf[0].component[0].ipv6.addr));
tft.pf[0].component[0].ipv6.prefixlen = 120;
#else
tft.pf[0].length = 33;
tft.pf[0].component[0].type =
GTP_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE;
memcpy(tft.pf[0].component[0].ipv6_mask.addr, ipsubnet.sub,
sizeof(tft.pf[0].component[0].ipv6_mask.addr));
memcpy(tft.pf[0].component[0].ipv6_mask.mask, ipsubnet.mask,
sizeof(tft.pf[0].component[0].ipv6_mask.mask));
#endif
tft.pf[0].num_of_component = 1;
} else if (tft.code == OGS_GTP_TFT_CODE_CREATE_NEW_TFT) {
tft.num_of_packet_filter = 4;
tft.pf[0].direction = 1;
tft.pf[0].identifier = 0;
tft.pf[0].precedence = 0x01;
tft.pf[0].length = 0x17;
tft.pf[0].component[0].type =
GTP_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE;
tft.pf[0].component[0].proto = 0x11; /* UDP */
tft.pf[0].component[1].type =
GTP_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE;
rv = ogs_ipsubnet(&ipsubnet, "172.20.166.84", NULL);
ogs_assert(rv == OGS_OK);
tft.pf[0].component[1].ipv4.addr = ipsubnet.sub[0];
tft.pf[0].component[1].ipv4.mask = ipsubnet.mask[0];
tft.pf[0].component[2].type =
GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE;
rv = ogs_ipsubnet(&ipsubnet, "172.18.128.20", NULL);
ogs_assert(rv == OGS_OK);
tft.pf[0].component[2].ipv4.addr = ipsubnet.sub[0];
tft.pf[0].component[2].ipv4.mask = ipsubnet.mask[0];
tft.pf[0].component[3].type =
GTP_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE;
tft.pf[0].component[3].port.low = 20001;
tft.pf[0].num_of_component = 4;
tft.pf[1].direction = 2;
tft.pf[1].identifier = 1;
tft.pf[1].precedence = 0x02;
tft.pf[1].length = 0x17;
tft.pf[1].component[0].type =
GTP_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE;
tft.pf[1].component[0].proto = 0x11; /* UDP */
tft.pf[1].component[1].type =
GTP_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE;
rv = ogs_ipsubnet(&ipsubnet, "172.20.166.84", NULL);
ogs_assert(rv == OGS_OK);
tft.pf[1].component[1].ipv4.addr = ipsubnet.sub[0];
tft.pf[1].component[1].ipv4.mask = ipsubnet.mask[0];
tft.pf[1].component[2].type =
GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE;
rv = ogs_ipsubnet(&ipsubnet, "172.18.128.20", NULL);
ogs_assert(rv == OGS_OK);
tft.pf[1].component[2].ipv4.addr = ipsubnet.sub[0];
tft.pf[1].component[2].ipv4.mask = ipsubnet.mask[0];
tft.pf[1].component[3].type =
GTP_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE;
tft.pf[1].component[3].port.low = 20360;
tft.pf[1].num_of_component = 4;
tft.pf[2].direction = 1;
tft.pf[2].identifier = 2;
tft.pf[2].precedence = 0x03;
tft.pf[2].length = 0x17;
tft.pf[2].component[0].type =
GTP_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE;
tft.pf[2].component[0].proto = 0x11; /* UDP */
tft.pf[2].component[1].type =
GTP_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE;
rv = ogs_ipsubnet(&ipsubnet, "172.20.166.84", NULL);
ogs_assert(rv == OGS_OK);
tft.pf[2].component[1].ipv4.addr = ipsubnet.sub[0];
tft.pf[2].component[1].ipv4.mask = ipsubnet.mask[0];
tft.pf[2].component[2].type =
GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE;
rv = ogs_ipsubnet(&ipsubnet, "172.18.128.20", NULL);
ogs_assert(rv == OGS_OK);
tft.pf[2].component[2].ipv4.addr = ipsubnet.sub[0];
tft.pf[2].component[2].ipv4.mask = ipsubnet.mask[0];
tft.pf[2].component[3].type =
GTP_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE;
tft.pf[2].component[3].port.low = 20002;
tft.pf[2].num_of_component = 4;
tft.pf[3].direction = 2;
tft.pf[3].identifier = 3;
tft.pf[3].precedence = 0x04;
tft.pf[3].length = 0x17;
tft.pf[3].component[0].type =
GTP_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE;
tft.pf[3].component[0].proto = 0x11; /* UDP */
tft.pf[3].component[1].type =
GTP_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE;
rv = ogs_ipsubnet(&ipsubnet, "172.20.166.84", NULL);
ogs_assert(rv == OGS_OK);
tft.pf[3].component[1].ipv4.addr = ipsubnet.sub[0];
tft.pf[3].component[1].ipv4.mask = ipsubnet.mask[0];
tft.pf[3].component[2].type =
GTP_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE;
rv = ogs_ipsubnet(&ipsubnet, "172.18.128.20", NULL);
ogs_assert(rv == OGS_OK);
tft.pf[3].component[2].ipv4.addr = ipsubnet.sub[0];
tft.pf[3].component[2].ipv4.mask = ipsubnet.mask[0];
tft.pf[3].component[3].type =
GTP_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE;
tft.pf[3].component[3].port.low = 20361;
tft.pf[3].num_of_component = 4;
}
tad->length = ogs_gtp_build_tft(&octet,
&tft, tad->buffer, OGS_GTP_MAX_TRAFFIC_FLOW_TEMPLATE);
if (ul_mbr || dl_mbr || ul_gbr || dl_gbr) {
req->presencemask |= OGS_NAS_BEARER_RESOURCE_MODIFICATION_REQUEST_REQUIRED_TRAFFIC_FLOW_QOS_PRESENT;
qos->length = 5;
qos->qci = qci;
qos->ul_mbr = ul_mbr;
qos->dl_mbr = dl_mbr;
qos->ul_gbr = ul_gbr;
qos->dl_gbr = dl_gbr;
}
emmbuf = ogs_nas_plain_encode(&message);
message.h.security_header_type =
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
message.h.message_authentication_code = htobe32(mac);
message.h.sequence_number = seq;
ogs_assert(ogs_pkbuf_push(emmbuf, sizeof(ogs_nas_security_header_t)));
memcpy(emmbuf->data, &message.h, sizeof(ogs_nas_security_header_t));
*pkbuf = emmbuf;
}
int tests1ap_build_bearer_resource_modification_request(
ogs_pkbuf_t **pkbuf,
uint32_t mme_ue_s1ap_id, uint32_t enb_ue_s1ap_id,
uint8_t pti, uint32_t mac, uint8_t seq, uint8_t ebi,
uint8_t tft_code, uint8_t qci,
uint8_t ul_mbr, uint8_t dl_mbr, uint8_t ul_gbr, uint8_t dl_gbr)
{
int rv;
ogs_pkbuf_t *emmbuf = NULL;
S1AP_S1AP_PDU_t pdu;
S1AP_InitiatingMessage_t *initiatingMessage = NULL;
S1AP_UplinkNASTransport_t *UplinkNASTransport = NULL;
S1AP_UplinkNASTransport_IEs_t *ie = NULL;
S1AP_MME_UE_S1AP_ID_t *MME_UE_S1AP_ID = NULL;
S1AP_ENB_UE_S1AP_ID_t *ENB_UE_S1AP_ID = NULL;
S1AP_NAS_PDU_t *NAS_PDU = NULL;
S1AP_EUTRAN_CGI_t *EUTRAN_CGI = NULL;
S1AP_TAI_t *TAI = NULL;
memset(&pdu, 0, sizeof (S1AP_S1AP_PDU_t));
pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage =
CALLOC(1, sizeof(S1AP_InitiatingMessage_t));
initiatingMessage = pdu.choice.initiatingMessage;
initiatingMessage->procedureCode =
S1AP_ProcedureCode_id_uplinkNASTransport;
initiatingMessage->criticality = S1AP_Criticality_ignore;
initiatingMessage->value.present =
S1AP_InitiatingMessage__value_PR_UplinkNASTransport;
UplinkNASTransport = &initiatingMessage->value.choice.UplinkNASTransport;
ie = CALLOC(1, sizeof(S1AP_UplinkNASTransport_IEs_t));
ASN_SEQUENCE_ADD(&UplinkNASTransport->protocolIEs, ie);
ie->id = S1AP_ProtocolIE_ID_id_MME_UE_S1AP_ID;
ie->criticality = S1AP_Criticality_reject;
ie->value.present =
S1AP_UplinkNASTransport_IEs__value_PR_MME_UE_S1AP_ID;
MME_UE_S1AP_ID = &ie->value.choice.MME_UE_S1AP_ID;
ie = CALLOC(1, sizeof(S1AP_UplinkNASTransport_IEs_t));
ASN_SEQUENCE_ADD(&UplinkNASTransport->protocolIEs, ie);
ie->id = S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID;
ie->criticality = S1AP_Criticality_reject;
ie->value.present =
S1AP_UplinkNASTransport_IEs__value_PR_ENB_UE_S1AP_ID;
ENB_UE_S1AP_ID = &ie->value.choice.ENB_UE_S1AP_ID;
ie = CALLOC(1, sizeof(S1AP_UplinkNASTransport_IEs_t));
ASN_SEQUENCE_ADD(&UplinkNASTransport->protocolIEs, ie);
ie->id = S1AP_ProtocolIE_ID_id_NAS_PDU;
ie->criticality = S1AP_Criticality_reject;
ie->value.present = S1AP_UplinkNASTransport_IEs__value_PR_NAS_PDU;
NAS_PDU = &ie->value.choice.NAS_PDU;
build_bearer_resource_modification_request(
&emmbuf, pti, mac, seq, ebi,
tft_code, qci, ul_mbr, dl_mbr, ul_gbr, dl_gbr);
ogs_assert(emmbuf);
NAS_PDU->size = emmbuf->len;
NAS_PDU->buf = CALLOC(NAS_PDU->size, sizeof(uint8_t));
memcpy(NAS_PDU->buf, emmbuf->data, NAS_PDU->size);
ogs_pkbuf_free(emmbuf);
*MME_UE_S1AP_ID = mme_ue_s1ap_id;
*ENB_UE_S1AP_ID = enb_ue_s1ap_id;
*pkbuf = ogs_s1ap_encode(&pdu);
if (*pkbuf == NULL) {
ogs_error("ogs_s1ap_encode() failed");
return OGS_ERROR;
}
return OGS_OK;
}
int tests1ap_build_path_switch_request(
ogs_pkbuf_t **pkbuf, int target,
uint32_t mme_ue_s1ap_id, uint32_t enb_ue_s1ap_id,

View File

@ -108,6 +108,14 @@ int tests1ap_build_modify_bearer_accept(
ogs_pkbuf_t **pkbuf, int i);
int tests1ap_build_deactivate_bearer_accept(
ogs_pkbuf_t **pkbuf, int i);
int tests1ap_build_bearer_resource_allocation_request(
ogs_pkbuf_t **pkbuf, int i);
int tests1ap_build_bearer_resource_modification_request(
ogs_pkbuf_t **pkbuf,
uint32_t mme_ue_s1ap_id, uint32_t enb_ue_s1ap_id,
uint8_t pti, uint32_t mac, uint8_t seq, uint8_t ebi,
uint8_t tft_code, uint8_t qci,
uint8_t ul_mbr, uint8_t dl_mbr, uint8_t ul_gbr, uint8_t dl_gbr);
int tests1ap_build_path_switch_request(
ogs_pkbuf_t **pkbuf, int target,
uint32_t mme_ue_s1ap_id, uint32_t enb_ue_s1ap_id,

View File

@ -270,6 +270,87 @@ static void volte_test1(abts_case *tc, void *data)
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
ogs_msleep(50);
/* Send Bearer resource allocation request */
rv = tests1ap_build_bearer_resource_allocation_request(&sendbuf, msgindex);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Bearer resource allocation reject */
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
ogs_pkbuf_free(recvbuf);
/* Send Bearer resource modification request */
rv = tests1ap_build_bearer_resource_modification_request(&sendbuf,
1, 1, 3, 0x3f426e62, 7, 7,
OGS_GTP_TFT_CODE_NO_TFT_OPERATION,
1, 0, 0, 0, 0);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive Bearer resource modification reject */
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
ogs_pkbuf_free(recvbuf);
/* Send Bearer resource modification request */
rv = tests1ap_build_bearer_resource_modification_request(&sendbuf,
1, 1, 4, 0xdc64fbbc, 8, 7,
OGS_GTP_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT,
1, 44, 55, 22, 33);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive E-RAB Modify Request +
* Modify EPS bearer context request */
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
ogs_pkbuf_free(recvbuf);
/* Send Modify EPS bearer context accept */
rv = tests1ap_build_modify_bearer_accept(&sendbuf, msgindex+1);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send E-RAB Modify Response */
rv = tests1ap_build_e_rab_modify_response(&sendbuf, msgindex+1);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Bearer resource modification request */
rv = tests1ap_build_bearer_resource_modification_request(&sendbuf,
1, 1, 5, 0x87a44610, 9, 7,
OGS_GTP_TFT_CODE_REPLACE_PACKET_FILTERS_IN_EXISTING,
1, 0, 0, 0, 0);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Receive E-RAB Modify Request +
* Modify EPS bearer context request */
recvbuf = testenb_s1ap_read(s1ap);
ABTS_PTR_NOTNULL(tc, recvbuf);
ogs_pkbuf_free(recvbuf);
/* Send E-RAB Modify Response */
rv = tests1ap_build_e_rab_modify_response(&sendbuf, msgindex+1);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Modify EPS bearer context accept */
rv = tests1ap_build_modify_bearer_accept(&sendbuf, msgindex+2);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
rv = testenb_s1ap_send(s1ap, sendbuf);
ABTS_INT_EQUAL(tc, OGS_OK, rv);
/* Send Session-Termination-Request */
pcscf_rx_send_str(rx_sid);