Commit a7358548 authored by gauthier's avatar gauthier

gtpv2c

parent 88b7499e
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file 3gpp_29.274.cpp
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#include "3gpp_29.274.hpp"
#include <string>
#include <string.h>
using namespace oai::cn::proto::gtpv2c;
using namespace oai::cn::core;
static const char* interface_type2char[40] = {
"S1_U_ENODEB_GTP_U",
"S1_U_SGW_GTP_U",
"S12_RNC_GTP_U",
"S12_SGW_GTP_U",
"S5_S8_SGW_GTP_U",
"S5_S8_PGW_GTP_U",
"S5_S8_SGW_GTP_C",
"S5_S8_PGW_GTP_C",
"S5_S8_SGW_PMIPv6",
"S5_S8_PGW_PMIPv6",
"S11_MME_GTP_C",
"S11_S4_SGW_GTP_C",
"S10_MME_GTP_C",
"S3_MME_GTP_C",
"S3_SGSN_GTP_C",
"S4_SGSN_GTP_U",
"S4_SGW_GTP_U",
"S4_SGSN_GTP_C",
"S16_SGSN_GTP_C",
"ENODEB_GTP_U_DL_DATA_FORWARDING",
"ENODEB_GTP_U_UL_DATA_FORWARDING",
"RNC_GTP_U_DATA_FORWARDING",
"SGSN_GTP_U_DATA_FORWARDING",
"SGW_UPF_GTP_U_DL_DATA_FORWARDING",
"SM_MBMS_GW_GTP_C",
"SN_MBMS_GW_GTP_C",
"SM_MME_GTP_C",
"SN_SGSN_GTP_C",
"SGW_GTP_U_UL_DATA_FORWARDING",
"SN_SGSN_GTP_U",
"S2B_EPDG_GTP_C",
"S2B_U_EPDG_GTP_U",
"S2B_PGW_GTP_C",
"S2B_U_PGW_GTP_U",
"S2A_TWAN_GTP_U",
"S2A_TWAN_GTP_C",
"S2A_PGW_GTP_C",
"S2A_PGW_GTP_U",
"S11_MME_GTP_U",
"S11_SGW_GTP_U"};
// From https://stackoverflow.com/a/2603254
static unsigned char lookup[16] = {
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf, };
uint8_t reverse_bits(uint8_t n) {
// Reverse the top and bottom nibble then swap them.
return (lookup[n&0b1111] << 4) | lookup[n>>4];
}
//------------------------------------------------------------------------------
std::string oai::cn::core::mccToString(const uint8_t digit1, const uint8_t digit2, const uint8_t digit3)
{
std::string s = {};
uint16_t mcc16 = digit1*100+digit2*10+digit3;
//s.append(std::to_string(digit1)).append(std::to_string(digit2)).append(std::to_string(digit3));
s.append(std::to_string(mcc16));
return s;
}
//------------------------------------------------------------------------------
std::string oai::cn::core::mncToString(const uint8_t digit1, const uint8_t digit2, const uint8_t digit3)
{
std::string s = {};
uint16_t mcc16 = 0;
if (digit3 == 0x0F) {
mcc16 = digit1*10+digit2;
} else {
mcc16 = digit1*100+digit2*10+digit3;
}
s.append(std::to_string(mcc16));
return s;
}
//------------------------------------------------------------------------------
std::string oai::cn::core::toString(const oai::cn::core::imsi_t& imsi)
{
std::string s = {};
int l_i = 0;
int l_j = 0;
while(l_i < IMSI_BCD8_SIZE) {
if((imsi.u1.b[l_i] & 0xf) > 9)
break;
s.append(std::to_string(imsi.u1.b[l_i] & 0xf));
l_j++;
if(((imsi.u1.b[l_i] & 0xf0) >> 4) > 9)
break;
s.append(std::to_string((imsi.u1.b[l_i] & 0xf0) >> 4));
l_j++;
l_i++;
}
return s;
}
//------------------------------------------------------------------------------
std::string oai::cn::core::toString(const oai::cn::core::pdn_type_t& pdn_type)
{
switch (pdn_type.pdn_type) {
case PDN_TYPE_E_IPV4: return std::string("IPV4"); break;
case PDN_TYPE_E_IPV6: return std::string("IPV6"); break;
case PDN_TYPE_E_IPV4V6: return std::string("IPV4V6"); break;
case PDN_TYPE_E_NON_IP: return std::string("NON_IP"); break;
default:
return std::to_string(pdn_type.pdn_type);
}
}
//------------------------------------------------------------------------------
std::string oai::cn::core::toString(const oai::cn::core::interface_type_e& interface_type)
{
if ((interface_type >= INTERFACE_TYPE_MIN) && (interface_type <= INTERFACE_TYPE_MAX)) {
return std::string(interface_type2char[interface_type]);
} else {
return std::to_string(interface_type);
}
}
//------------------------------------------------------------------------------
std::string oai::cn::core::toString(const oai::cn::core::fteid_t& fteid)
{
std::string s = {};
core::interface_type_e interface_type = static_cast<core::interface_type_e>(fteid.interface_type);
if ((fteid.v4) || (fteid.v6)) {
s.append("Interface type=").append(toString(interface_type));
s.append(", TEID=").append(std::to_string(fteid.teid_gre_key));
if (fteid.v4) {
s.append(", IPv4=").append(toString(fteid.ipv4_address));
}
if (fteid.v6) {
s.append(", IPv6=").append(toString(fteid.ipv6_address));
}
} else {
s.append("null_fteid");
}
return s;
}
//------------------------------------------------------------------------------
struct in_addr oai::cn::core::fromString(const std::string addr4)
{
unsigned char buf[sizeof(struct in6_addr)] = {};
int s = inet_pton(AF_INET, addr4.c_str(), buf);
struct in_addr * ia = (struct in_addr *)buf;
return *ia;
}
//------------------------------------------------------------------------------
std::string oai::cn::core::toString(const struct in_addr& inaddr)
{
std::string s = {};
char str[INET6_ADDRSTRLEN] = {};
if (inet_ntop(AF_INET, (const void *)&inaddr, str, INET6_ADDRSTRLEN) == NULL) {
s.append("Error in_addr");
} else {
s.append(str);
}
return s;
}
//------------------------------------------------------------------------------
std::string oai::cn::core::toString(const struct in6_addr& in6addr)
{
std::string s = {};
char str[INET6_ADDRSTRLEN] = {};
if (inet_ntop(AF_INET6, (const void *)&in6addr, str, INET6_ADDRSTRLEN) == nullptr) {
s.append("Error in6_addr");
} else {
s.append(str);
}
return s;
}
//------------------------------------------------------------------------------
std::string oai::cn::core::toString(const oai::cn::core::bearer_qos_t& bearer_qos)
{
std::string s = {};
s.append("MBR UL=").append(std::to_string(bearer_qos.maximum_bit_rate_for_uplink));
s.append(", MBR DL=").append(std::to_string(bearer_qos.maximum_bit_rate_for_downlink));
s.append(", GBR UL=").append(std::to_string(bearer_qos.guaranted_bit_rate_for_uplink));
s.append(", GBR DL=").append(std::to_string(bearer_qos.guaranted_bit_rate_for_downlink));
s.append(", PCI=").append(std::to_string(bearer_qos.pci));
s.append(", PL=").append(std::to_string(bearer_qos.pl));
s.append(", PVI=").append(std::to_string(bearer_qos.pvi));
s.append(", QCI=").append(std::to_string(bearer_qos.label_qci));
return s;
}
//------------------------------------------------------------------------------
std::string oai::cn::core::toString(const oai::cn::core::ecgi_field_t& ef)
{
std::string s = {};
std::string mccs = mccToString(ef.mcc_digit_1, ef.mcc_digit_2,ef.mcc_digit_3);
std::string mncs = mncToString(ef.mnc_digit_1, ef.mnc_digit_2,ef.mnc_digit_3);
s.append("mcc=").append(mccs).append(", MNC=").append(mncs);
s.append(", ECI=").append(std::to_string(ef.eci));
uint32_t e_utran_cell_identifier = ef.e_utran_cell_identifier[0] << 16;
e_utran_cell_identifier |= (ef.e_utran_cell_identifier[1] << 8);
e_utran_cell_identifier |= ef.e_utran_cell_identifier[2];
s.append(", EUCI=").append(std::to_string(e_utran_cell_identifier));
return s;
}
//------------------------------------------------------------------------------
bool oai::cn::core::is_fteid_zero(const fteid_t& f) {return (not(f.v4==1) and not(f.v6==1));};
bool oai::cn::core::is_fteid_equal(const fteid_t& f1, const fteid_t& f2) {return ((f1.teid_gre_key == f2.teid_gre_key) and
((f1.v4 == 1) and(f2.v4 == 1) and (f1.ipv4_address.s_addr == f2.ipv4_address.s_addr)) and
((f1.v6 == 1) and(f2.v6 == 1) and (f1.ipv6_address.s6_addr32[0] == f2.ipv6_address.s6_addr32[0]) and
(f1.ipv6_address.s6_addr32[1] == f2.ipv6_address.s6_addr32[1]) and
(f1.ipv6_address.s6_addr32[2] == f2.ipv6_address.s6_addr32[2]) and
(f1.ipv6_address.s6_addr32[3] == f2.ipv6_address.s6_addr32[3])) and
(f1.interface_type == f2.interface_type) and
(f1.v4 == f2.v4) and
(f1.v6 == f2.v6));
};
//------------------------------------------------------------------------------
gtpv2c_ie * gtpv2c_ie::new_gtpv2c_ie_from_stream(std::istream& is) {
gtpv2c_tlv tlv;
tlv.load_from(is);
if (tlv.length) {
switch (tlv.type) {
case GTP_IE_IMSI: {
gtpv2c_imsi_ie *ie = new gtpv2c_imsi_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_CAUSE: {
gtpv2c_cause_ie *ie = new gtpv2c_cause_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_RECOVERY_RESTART_COUNTER: {
gtpv2c_recovery_ie *ie = new gtpv2c_recovery_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_ACCESS_POINT_NAME: {
gtpv2c_access_point_name_ie *ie = new gtpv2c_access_point_name_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_AGGREGATE_MAXIMUM_BIT_RATE: {
gtpv2c_aggregate_maximum_bit_rate_ie *ie = new gtpv2c_aggregate_maximum_bit_rate_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_EPS_BEARER_ID: {
gtpv2c_eps_bearer_id_ie *ie = new gtpv2c_eps_bearer_id_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_IP_ADDRESS: {
gtpv2c_ip_address_ie *ie = new gtpv2c_ip_address_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_MOBILE_EQUIPMENT_IDENTITY: {
gtpv2c_mei_ie *ie = new gtpv2c_mei_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_MSISDN: {
gtpv2c_msisdn_ie *ie = new gtpv2c_msisdn_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_INDICATION: {
gtpv2c_indication_ie *ie = new gtpv2c_indication_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_PROTOCOL_CONFIGURATION_OPTIONS: {
gtpv2c_pco_ie *ie = new gtpv2c_pco_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_PDN_ADDRESS_ALLOCATION: {
gtpv2c_paa_ie *ie = new gtpv2c_paa_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_BEARER_QUALITY_OF_SERVICE: {
gtpv2c_bearer_qos_ie *ie = new gtpv2c_bearer_qos_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_FLOW_QUALITY_OF_SERVICE: {
gtpv2c_flow_qos_ie *ie = new gtpv2c_flow_qos_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_RAT_TYPE: {
gtpv2c_rat_type_ie *ie = new gtpv2c_rat_type_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_SERVING_NETWORK: {
gtpv2c_serving_network_ie *ie = new gtpv2c_serving_network_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_EPS_BEARER_LEVEL_TRAFFIC_FLOW_TEMPLATE: {
gtpv2c_bearer_tft_ie *ie = new gtpv2c_bearer_tft_ie(tlv);
ie->load_from(is);
return ie;
}
break;
//case GTP_IE_TRAFFIC_AGGREGATE_DESCRIPTION:
case GTP_IE_USER_LOCATION_INFORMATION: {
gtpv2c_user_location_information_ie *ie = new gtpv2c_user_location_information_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_FULLY_QUALIFIED_TUNNEL_ENDPOINT_IDENTIFIER: {
gtpv2c_fully_qualified_teid_ie *ie = new gtpv2c_fully_qualified_teid_ie(tlv);
ie->load_from(is);
return ie;
}
break;
//case GTP_IE_TMSI:
//case GTP_IE_GLOBAL_CN_ID:
//case GTP_IE_S103_PDN_DATA_FORWARDING_INFO:
//case GTP_IE_S1U_DATA_FORWARDING_INFO:
case GTP_IE_DELAY_VALUE: {
gtpv2c_delay_value_ie *ie = new gtpv2c_delay_value_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_BEARER_CONTEXT: {
gtpv2c_bearer_context_ie *ie = new gtpv2c_bearer_context_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_CHARGING_ID: {
gtpv2c_charging_id_ie *ie = new gtpv2c_charging_id_ie(tlv);
ie->load_from(is);
return ie;
}
break;
//case GTP_IE_CHARGING_CHARACTERISTICS:
//case GTP_IE_TRACE_INFORMATION:
case GTP_IE_BEARER_FLAGS: {
gtpv2c_bearer_flags_ie *ie = new gtpv2c_bearer_flags_ie(tlv);
ie->load_from(is);
return ie;
}
break;
case GTP_IE_PDN_TYPE: {
gtpv2c_pdn_type_ie *ie = new gtpv2c_pdn_type_ie(tlv);
ie->load_from(is);
return ie;
}
break;
//case GTP_IE_PROCEDURE_TRANSACTION_ID:
//case GTP_IE_MM_CONTEXT_GSM_KEY_AND_TRIPLETS:
//case GTP_IE_MM_CONTEXT_UMTS_KEY_USED_CIPHER_AND_QUINTUPLETS:
//case GTP_IE_MM_CONTEXT_GSM_KEY_USED_CIPHER_AND_QUINTUPLETS:
//case GTP_IE_MM_CONTEXT_UMTS_KEY_AND_QUINTUPLETS:
//case GTP_IE_MM_CONTEXT_EPS_SECURITY_CONTEXT_AND_QUADRUPLETS:
//case GTP_IE_MM_CONTEXT_UMTS_KEY_QUADRUPLETS_AND_QUINTUPLETS:
//case GTP_IE_PDN_CONNECTION:
//case GTP_IE_PDU_NUMBERS:
//case GTP_IE_PACKET_TMSI:
//case GTP_IE_P_TMSI_SIGNATURE:
//case GTP_IE_HOP_COUNTER:
case GTP_IE_UE_TIME_ZONE: {
gtpv2c_ue_time_zone_ie *ie = new gtpv2c_ue_time_zone_ie(tlv);
ie->load_from(is);
return ie;
}
break;
//case GTP_IE_TRACE_REFERENCE:
//case GTP_IE_COMPLETE_REQUEST_MESSAGE:
//case GTP_IE_GUTI:
//case GTP_IE_FULLY_QUALIFIED_CONTAINER:
//case GTP_IE_FULLY_QUALIFIED_CAUSE:
//case GTP_IE_PLMN_ID:
//case GTP_IE_TARGET_IDENTIFICATION:
//case GTP_IE_PACKET_FLOW_ID:
//case GTP_IE_RAB_CONTEXT:
//case GTP_IE_SOURCE_RNC_PDCP_CONTEXT_INFO:
//case GTP_IE_PORT_NUMBER:
case GTP_IE_APN_RESTRICTION: {
gtpv2c_apn_restriction_ie *ie = new gtpv2c_apn_restriction_ie(tlv);
ie->load_from(is);
return ie;
}
case GTP_IE_SELECTION_MODE: {
gtpv2c_selection_mode_ie *ie = new gtpv2c_selection_mode_ie(tlv);
ie->load_from(is);
return ie;
}
break;
//case GTP_IE_SOURCE_IDENTIFICATION:
//case GTP_IE_CHANGE_REPORTING_ACTION:
case GTP_IE_FQ_CSID: {
gtpv2c_fq_csid_ie *ie = new gtpv2c_fq_csid_ie(tlv);
ie->load_from(is);
return ie;
}
break;
//case GTP_IE_CHANNEL_NEEDED:
//case GTP_IE_EMLPP_PRIORITY:
case GTP_IE_NODE_TYPE: {
gtpv2c_node_type_ie *ie = new gtpv2c_node_type_ie(tlv);
ie->load_from(is);
return ie;
}
break;
//case GTP_IE_FULLY_QUALIFIED_DOMAIN_NAME:
//case GTP_IE_TRANSACTION_IDENTIFIER:
//case GTP_IE_MBMS_SESSION_DURATION:
//case GTP_IE_MBMS_SERVICE_AREA:
//case GTP_IE_MBMS_SESSION_IDENTIFIER:
//case GTP_IE_MBMS_FLOW_IDENTIFIER:
//case GTP_IE_MBMS_IP_MULTICAST_DISTRIBUTION:
//case GTP_IE_MBMS_DISTRIBUTION_ACKNOWLEDGE:
//case GTP_IE_RFSP_INDEX:
//case GTP_IE_USER_CSG_INFORMATION:
//case GTP_IE_CSG_REPORTING_ACTION:
//case GTP_IE_CSG_ID:
//case GTP_IE_CSG_MEMBERSHIP_INDICATION:
//case GTP_IE_SERVICE_INDICATOR:
//case GTP_IE_DETACH_TYPE:
//case GTP_IE_LOCAL_DISTINGUISHED_NAME:
case GTP_IE_NODE_FEATURES: {
gtpv2c_node_features_ie *ie = new gtpv2c_node_features_ie(tlv);
ie->load_from(is);
return ie;
}
break;
//case GTP_IE_MBMS_TIME_TO_DATA_TRANSFER:
//case GTP_IE_THROTTLING:
//case GTP_IE_ALLOCATION_RETENTION_PRIORITY:
//case GTP_IE_EPC_TIMER:
//case GTP_IE_SIGNALLING_PRIORITY_INDICATION:
//case GTP_IE_TMGI:
//case GTP_IE_ADDITIONAL_MM_CONTEXT_FOR_SRVCC:
//case GTP_IE_ADDITIONAL_FLAGS_FOR_SRVCC:
//case GTP_IE_MDT_CONFIGURATION:
//case GTP_IE_ADDITIONAL_PROTOCOL_CONFIGURATION_OPTIONS:
//case GTP_IE_ABSOLUTE_TIME_OF_MBMS_DATA_TRANSFER:
//case GTP_IE_H_E_NB_INFORMATION_REPORTING:
//case GTP_IE_IPV4_CONFIGURATION_PARAMETERS:
//case GTP_IE_CHANGE_TO_REPORT_FLAGS:
//case GTP_IE_ACTION_INDICATION:
//case GTP_IE_TWAN_IDENTIFIER:
//case GTP_IE_ULI_TIMESTAMP:
//case GTP_IE_MBMS_FLAGS:
//case GTP_IE_RAN_NAS_CAUSE:
//case GTP_IE_CN_OPERATOR_SELECTION_ENTITY:
//case GTP_IE_TRUSTED_WLAN_MODE_INDICATION:
//case GTP_IE_NODE_NUMBER:
//case GTP_IE_NODE_IDENTIFIER:
//case GTP_IE_PRESENCE_REPORTING_AREA_ACTION:
//case GTP_IE_PRESENCE_REPORTING_AREA_INFORMATION:
//case GTP_IE_TWAN_IDENTIFIER_TIMESTAMP:
//case GTP_IE_OVERLOAD_CONTROL_INFORMATION:
//case GTP_IE_LOAD_CONTROL_INFORMATION:
//case GTP_IE_METRIC:
//case GTP_IE_SEQUENCE_NUMBER:
//case GTP_IE_APN_AND_RELATIVE_CAPACITY:
//case GTP_IE_PAGING_AND_SERVICE_INFORMATION:
//case GTP_IE_INTEGER_NUMBER:
//case GTP_IE_MILLISECOND_TIME_STAMP:
//case GTP_IE_MONITORING_EVENT_INFORMATION:
//case GTP_IE_ECGI_LIST:
//case GTP_IE_REMOTE_UE_CONTEXT:
//case GTP_IE_REMOTE_USER_ID:
//case GTP_IE_REMOTE_UE_IP_INFORMATION:
case GTP_IE_CIOT_OPTIMIZATIONS_SUPPORT_INDICATION: {
gtpv2c_ciot_optimizations_support_indication_ie *ie = new gtpv2c_ciot_optimizations_support_indication_ie(tlv);
ie->load_from(is);
return ie;
}
break;
//case GTP_IE_SCEF_PDN_CONNECTION:
//case GTP_IE_HEADER_COMPRESSION_CONFIGURATION:
//case GTP_IE_EXTENDED_PROTOCOL_CONFIGURATION_OPTIONS:
//case GTP_IE_SERVING_PLMN_RATE_CONTROL:
//case GTP_IE_COUNTER:
//case GTP_IE_MAPPED_UE_USAGE_TYPE:
//case GTP_IE_SECONDARY_RAT_USAGE_DATA_REPORT:
//case GTP_IE_UP_FUNCTION_SELECTION_INDICATION_FLAGS:
//case GTP_IE_PRIVATE_EXTENSION:
//case GTP_IE_WLAN_OFFLOADABILITY_INDICATION:
//case GTP_IE_MAXIMUM_PACKET_LOSS:
default:
Logger::gtpv2_c().error("Unknown GTP IE type %d (length %d)", tlv.get_type(), tlv.get_length());
return nullptr;
}
} else {
Logger::gtpv2_c().error("GTP IE type %d length %d", tlv.get_type(), tlv.get_length());
return nullptr;
}
}
//------------------------------------------------------------------------------
gtpv2c_msg::gtpv2c_msg(const gtpv2c_create_session_request& gtp_ies) : gtpv2c_msg_header() {
ies = {};
set_message_type(GTP_CREATE_SESSION_REQUEST);
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_IMSI) {std::shared_ptr<gtpv2c_imsi_ie> sie(new gtpv2c_imsi_ie(gtp_ies.imsi)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_MSISDN) {std::shared_ptr<gtpv2c_msisdn_ie> sie(new gtpv2c_msisdn_ie(gtp_ies.msisdn)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_MEI) {std::shared_ptr<gtpv2c_mei_ie> sie(new gtpv2c_mei_ie(gtp_ies.mei)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_ULI) {std::shared_ptr<gtpv2c_user_location_information_ie> sie(new gtpv2c_user_location_information_ie(gtp_ies.uli)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_SERVING_NETWORK) {std::shared_ptr<gtpv2c_serving_network_ie> sie(new gtpv2c_serving_network_ie(gtp_ies.serving_network)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_RAT_TYPE) {std::shared_ptr<gtpv2c_rat_type_ie> sie(new gtpv2c_rat_type_ie(gtp_ies.rat_type)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_INDICATION_FLAGS) {std::shared_ptr<gtpv2c_indication_ie> sie(new gtpv2c_indication_ie(gtp_ies.indication_flags)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_SENDER_FTEID_FOR_CONTROL_PLANE) {std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(gtp_ies.sender_fteid_for_cp)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_PGW_S5S8_ADDRESS_FOR_CONTROL_PLANE) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(gtp_ies.pgw_s5s8_address_for_cp));
sie.get()->tlv.set_instance(1);
add_ie(sie);
}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_APN) {std::shared_ptr<gtpv2c_access_point_name_ie> sie(new gtpv2c_access_point_name_ie(gtp_ies.apn)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_SELECTION_MODE) {std::shared_ptr<gtpv2c_selection_mode_ie> sie(new gtpv2c_selection_mode_ie(gtp_ies.selection_mode)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_PDN_TYPE) {std::shared_ptr<gtpv2c_pdn_type_ie> sie(new gtpv2c_pdn_type_ie(gtp_ies.pdn_type)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_PAA) {std::shared_ptr<gtpv2c_paa_ie> sie(new gtpv2c_paa_ie(gtp_ies.paa)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_APN_RESTRICTION) {std::shared_ptr<gtpv2c_apn_restriction_ie> sie(new
gtpv2c_apn_restriction_ie(gtp_ies.apn_restriction)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_APN_AMBR) {std::shared_ptr<gtpv2c_aggregate_maximum_bit_rate_ie> sie(new gtpv2c_aggregate_maximum_bit_rate_ie(gtp_ies.ambr)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_LINKED_EPS_BEARER_ID) {std::shared_ptr<gtpv2c_eps_bearer_id_ie> sie(new gtpv2c_eps_bearer_id_ie(gtp_ies.linked_eps_bearer_id)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_TRUSTED_WLAN_MODE_INDICATION) {}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_PCO) {std::shared_ptr<gtpv2c_pco_ie> sie(new gtpv2c_pco_ie(gtp_ies.pco)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_BEARER_CONTEXTS_TO_BE_CREATED) {
if (gtp_ies.bearer_contexts_to_be_created.size() > 0) {
for (auto i : gtp_ies.bearer_contexts_to_be_created) {
gtpv2c_grouped_ie *gie = new gtpv2c_grouped_ie(GTP_IE_BEARER_CONTEXT);
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_CREATED_WITHIN_CREATE_SESSION_REQUEST_PR_IE_EPS_BEARER_ID) {std::shared_ptr<gtpv2c_eps_bearer_id_ie> sie(new gtpv2c_eps_bearer_id_ie(i.eps_bearer_id)); gie->add_ie(sie);}
//TODO if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_CREATED_WITHIN_CREATE_SESSION_REQUEST_PR_IE_TFT) {std::shared_ptr<gtpv2c_traffic_flow_template_ie> sie(new gtpv2c_traffic_flow_template_ie(i.ambr)); gie->add_ie(sie);}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_CREATED_WITHIN_CREATE_SESSION_REQUEST_PR_IE_S1_U_ENB_FTEID) {std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s1_u_enb_fteid)); gie->add_ie(sie);}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_CREATED_WITHIN_CREATE_SESSION_REQUEST_PR_IE_S4_U_SGSN_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s4_u_sgsn_fteid));
sie.get()->tlv.set_instance(1);
gie->add_ie(sie);
}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_CREATED_WITHIN_CREATE_SESSION_REQUEST_PR_IE_S5_S8_U_SGW_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s5_s8_u_sgw_fteid));
sie.get()->tlv.set_instance(2);
gie->add_ie(sie);
}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_CREATED_WITHIN_CREATE_SESSION_REQUEST_PR_IE_S5_S8_U_PGW_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s5_s8_u_pgw_fteid));
sie.get()->tlv.set_instance(3);
gie->add_ie(sie);
}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_CREATED_WITHIN_CREATE_SESSION_REQUEST_PR_IE_S12_RNC_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s12_rnc_fteid));
sie.get()->tlv.set_instance(4);
gie->add_ie(sie);
}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_CREATED_WITHIN_CREATE_SESSION_REQUEST_PR_IE_S2B_U_EPDG_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s2b_u_epdg_fteid));
sie.get()->tlv.set_instance(5);
gie->add_ie(sie);
}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_CREATED_WITHIN_CREATE_SESSION_REQUEST_PR_IE_S2A_U_TWAN_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s2a_u_twan_fteid));
sie.get()->tlv.set_instance(6);
gie->add_ie(sie);
}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_CREATED_WITHIN_CREATE_SESSION_REQUEST_PR_IE_BEARER_LEVEL_QOS) {std::shared_ptr<gtpv2c_bearer_qos_ie> sie(new gtpv2c_bearer_qos_ie(i.bearer_level_qos)); gie->add_ie(sie);}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_CREATED_WITHIN_CREATE_SESSION_REQUEST_PR_IE_S11_U_MME_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s11_u_mme_fteid));
sie.get()->tlv.set_instance(7);
gie->add_ie(sie);
}
std::shared_ptr<gtpv2c_grouped_ie> sgie(gie);
add_ie(sgie);
}
}
}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_BEARER_CONTEXTS_TO_BE_REMOVED) {
if (gtp_ies.bearer_contexts_to_be_removed.size() > 0) {
for (auto i : gtp_ies.bearer_contexts_to_be_removed) {
gtpv2c_grouped_ie *gie = new gtpv2c_grouped_ie(GTP_IE_BEARER_CONTEXT);
gie->tlv.set_instance(1);
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_REMOVED_WITHIN_CREATE_SESSION_REQUEST_PR_IE_EPS_BEARER_ID) {std::shared_ptr<gtpv2c_eps_bearer_id_ie> sie(new gtpv2c_eps_bearer_id_ie(i.eps_bearer_id)); gie->add_ie(sie);}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_REMOVED_WITHIN_CREATE_SESSION_REQUEST_PR_IE_S4_U_SGSN_FTEID) {std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s4_u_sgsn_fteid)); gie->add_ie(sie);}
std::shared_ptr<gtpv2c_grouped_ie> sie(gie);
add_ie(sie);
}
}
}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_TRACE_INFORMATION) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_RECOVERY) {}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_MME_FQ_CSID) {std::shared_ptr<gtpv2c_fq_csid_ie> sie(new gtpv2c_fq_csid_ie(gtp_ies.mme_fq_csid));add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_SGW_FQ_CSID) {
std::shared_ptr<gtpv2c_fq_csid_ie> sie(new gtpv2c_fq_csid_ie(gtp_ies.sgw_fq_csid));
sie.get()->tlv.set_instance(1);
add_ie(sie);
}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_EPDG_FQ_CSID) {std::shared_ptr<gtpv2c_fq_csid_ie> sie(new gtpv2c_fq_csid_ie(gtp_ies.)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_TWAN_FQ_CSID) {std::shared_ptr<gtpv2c_fq_csid_ie> sie(new gtpv2c_fq_csid_ie(gtp_ies.)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_UE_TIME_ZONE) {std::shared_ptr<gtpv2c_ue_time_zone_ie> sie(new gtpv2c_ue_time_zone_ie(gtp_ies.ue_time_zone)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_UCI) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_CHARGING_CHARACTERISTICS) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_MME_S4_SGSN_LDN) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_SGW_LDN) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_EPDG_LDN) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_TWAN_LDN) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_SIGNALLING_PRIORITY_INDICATION) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_UE_LOCAL_IP_ADDRESS) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_UE_UDP_PORT) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_APCO) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_HENB_LOCAL_IP_ADDRESS) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_HENB_UDP_PORT) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_MME_S4_SGSN_IDENTIFIER) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_TWAN_IDENTIFIER) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_EPDG_IP_ADDRESS) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_CN_OPERATOR_SELECTION_ENTITY) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_PRESENCE_REPORTING_AREA_INFORMATION) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_MMES4_SGSN_OVERLOAD_CONTROL_INFORMATION) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_SGW_OVERLOAD_CONTROL_INFORMATION) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_TWAN_EPDG_OVERLOAD_CONTROL_INFORMATION) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_ORIGINATION_TIME_STAMP) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_MAXIMUM_WAIT_TIME) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_WLAN_LOCATION_INFORMATION) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_WLAN_LOCATION_TIMESTAMP) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_NBIFOM_CONTAINER) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_REMOTE_UE_CONTEXT_CONNECTED) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_3GPP_AAA_SERVER_IDENTIFIER) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_EPCO) {}{std::shared_ptr<gtpv2c_epco_ie> sie(new gtpv2c_epco_ie(gtp_ies.)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_SERVING_PLMN_RATE_CONTROL) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_MO_EXCEPTION_DATA_COUNTER) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_UE_TCP_PORT) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_MAPPED_UE_USAGE_TYPE) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_ULI_FOR_SGW) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_SGW_U_NODE_NAME) {}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_REQUEST_PR_IE_PRIVATE_EXTENSION) {}
}
//------------------------------------------------------------------------------
gtpv2c_msg::gtpv2c_msg(const gtpv2c_create_session_response& gtp_ies) : gtpv2c_msg_header() {
ies = {};
set_message_type(GTP_CREATE_SESSION_RESPONSE);
if (gtp_ies.cause.first) {std::shared_ptr<gtpv2c_cause_ie> sie(new gtpv2c_cause_ie(gtp_ies.cause.second)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_CHANGE_REPORTING_ACTION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_CSG_INFORMATION_REPORTING_ACTION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_HENB_INFORMATION_REPORTING) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
if (gtp_ies.sender_fteid_for_cp.first) {std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(gtp_ies.sender_fteid_for_cp.second)); add_ie(sie);}
if (gtp_ies.s5_s8_pgw_fteid.first) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(gtp_ies.s5_s8_pgw_fteid.second));
sie.get()->tlv.set_instance(1);
add_ie(sie);
}
if (gtp_ies.paa.first) {std::shared_ptr<gtpv2c_paa_ie> sie(new gtpv2c_paa_ie(gtp_ies.paa.second)); add_ie(sie);}
if (gtp_ies.apn_restriction.first) {std::shared_ptr<gtpv2c_apn_restriction_ie> sie(new gtpv2c_apn_restriction_ie(gtp_ies.apn_restriction.second)); add_ie(sie);}
if (gtp_ies.apn_ambr.first) {std::shared_ptr<gtpv2c_aggregate_maximum_bit_rate_ie> sie(new gtpv2c_aggregate_maximum_bit_rate_ie(gtp_ies.apn_ambr.second)); add_ie(sie);}
if (gtp_ies.linked_eps_bearer_id.first) {std::shared_ptr<gtpv2c_eps_bearer_id_ie> sie(new gtpv2c_eps_bearer_id_ie(gtp_ies.linked_eps_bearer_id.second)); add_ie(sie);}
if (gtp_ies.pco.first) {std::shared_ptr<gtpv2c_pco_ie> sie(new gtpv2c_pco_ie(gtp_ies.pco.second)); add_ie(sie);}
if (gtp_ies.bearer_contexts_created.first) {
if (gtp_ies.bearer_contexts_created.second.size() > 0) {
for (auto i : gtp_ies.bearer_contexts_created.second) {
gtpv2c_grouped_ie *gie = new gtpv2c_grouped_ie(GTP_IE_BEARER_CONTEXT);
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_CREATED_WITHIN_CREATE_SESSION_RESPONSE_PR_IE_EPS_BEARER_ID) {std::shared_ptr<gtpv2c_eps_bearer_id_ie> sie(new gtpv2c_eps_bearer_id_ie(i.eps_bearer_id)); gie->add_ie(sie);}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_CREATED_WITHIN_CREATE_SESSION_RESPONSE_PR_IE_CAUSE) {std::shared_ptr<gtpv2c_cause_ie> sie(new gtpv2c_cause_ie(i.cause)); gie->add_ie(sie);}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_CREATED_WITHIN_CREATE_SESSION_RESPONSE_PR_IE_S1_U_SGW_FTEID) {std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s1_u_sgw_fteid)); gie->add_ie(sie);}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_CREATED_WITHIN_CREATE_SESSION_RESPONSE_PR_IE_S4_U_SGW_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s4_u_sgw_fteid));
sie.get()->tlv.set_instance(1);
gie->add_ie(sie);
}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_CREATED_WITHIN_CREATE_SESSION_RESPONSE_PR_IE_S5_S8_U_PGW_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s5_s8_u_pgw_fteid));
sie.get()->tlv.set_instance(2);
gie->add_ie(sie);
}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_CREATED_WITHIN_CREATE_SESSION_RESPONSE_PR_IE_S12_SGW_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s12_sgw_fteid));
sie.get()->tlv.set_instance(3);
gie->add_ie(sie);
}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_CREATED_WITHIN_CREATE_SESSION_RESPONSE_PR_IE_S5_S8_BEARER_LEVEL_QOS) {std::shared_ptr<gtpv2c_bearer_qos_ie> sie(new gtpv2c_bearer_qos_ie(i.bearer_level_qos)); gie->add_ie(sie);}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_CREATED_WITHIN_CREATE_SESSION_RESPONSE_PR_IE_CHARGING_ID) {std::shared_ptr<gtpv2c_charging_id_ie> sie(new gtpv2c_charging_id_ie(i.charging_id)); gie->add_ie(sie);}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_CREATED_WITHIN_CREATE_SESSION_RESPONSE_PR_IE_BEARER_FLAGS) {std::shared_ptr<gtpv2c_bearer_flags_ie> sie(new gtpv2c_bearer_flags_ie(i.bearer_flags)); gie->add_ie(sie);}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_CREATED_WITHIN_CREATE_SESSION_RESPONSE_PR_IE_S11_U_SGW_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s11_u_sgw_fteid));
sie.get()->tlv.set_instance(6);
gie->add_ie(sie);
}
std::shared_ptr<gtpv2c_grouped_ie> sie(gie);
add_ie(sie);
}
}
}
if (gtp_ies.bearer_contexts_marked_for_removal.first) {
if (gtp_ies.bearer_contexts_marked_for_removal.second.size() > 0) {
for (auto i : gtp_ies.bearer_contexts_marked_for_removal.second) {
gtpv2c_grouped_ie *gie = new gtpv2c_grouped_ie(GTP_IE_BEARER_CONTEXT);
gie->tlv.set_instance(1);
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_MARKED_FOR_REMOVAL_WITHIN_CREATE_SESSION_RESPONSE_PR_IE_EPS_BEARER_ID) {std::shared_ptr<gtpv2c_eps_bearer_id_ie> sie(new gtpv2c_eps_bearer_id_ie(i.eps_bearer_id)); gie->add_ie(sie);}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_MARKED_FOR_REMOVAL_WITHIN_CREATE_SESSION_RESPONSE_PR_IE_CAUSE) {std::shared_ptr<gtpv2c_cause_ie> sie(new gtpv2c_cause_ie(i.cause)); gie->add_ie(sie);}
std::shared_ptr<gtpv2c_grouped_ie> sie(gie);
add_ie(sie);
}
}
}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_RECOVERY) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_CHARGING_GATEWAY_NAME) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_CHARGING_GATEWAY_ADDRESS) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
if (gtp_ies.pgw_fq_csid.first) {std::shared_ptr<gtpv2c_fq_csid_ie> sie(new gtpv2c_fq_csid_ie(gtp_ies.pgw_fq_csid.second));add_ie(sie);}
if (gtp_ies.sgw_fq_csid.first) {
std::shared_ptr<gtpv2c_fq_csid_ie> sie(new gtpv2c_fq_csid_ie(gtp_ies.sgw_fq_csid.second));
sie.get()->tlv.set_instance(1);
add_ie(sie);
}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_SGW_LDN) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_PGW_LDN) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_PGW_BACK_OFF_TIME) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.pgw_back_off_time)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_APCO) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_TRUSTED_WLAN_IPV4_PARAMETERS) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
if (gtp_ies.indication_flags.first) {std::shared_ptr<gtpv2c_indication_ie> sie(new gtpv2c_indication_ie(gtp_ies.indication_flags.second)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_PRESENCE_REPORTING_AREA_ACTION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_PGW_NODE_LEVEL_LOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_PGW_APN_LEVEL_LOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_SGW_NODE_LEVEL_LOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_PGW_OVERLOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_SGW_OVERLOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_NBIFOM_CONTAINER) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_PDN_CONNECTION_CHARGING_ID) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_EPCO) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_CREATE_SESSION_RESPONSE_PR_IE_PRIVATE_EXTENSION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
}
//------------------------------------------------------------------------------
gtpv2c_msg::gtpv2c_msg(const gtpv2c_delete_session_request& gtp_ies) : gtpv2c_msg_header() {
ies = {};
set_message_type(GTP_DELETE_SESSION_REQUEST);
if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_CAUSE) {std::shared_ptr<gtpv2c_cause_ie> sie(new gtpv2c_cause_ie(gtp_ies.cause)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_LINKED_EPS_BEARER_ID) {std::shared_ptr<gtpv2c_eps_bearer_id_ie> sie(new gtpv2c_eps_bearer_id_ie(gtp_ies.linked_eps_bearer_id)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_ULI) {std::shared_ptr<gtpv2c_user_location_information_ie> sie(new gtpv2c_user_location_information_ie(gtp_ies.uli)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_INDICATION_FLAGS) {std::shared_ptr<gtpv2c_indication_ie> sie(new gtpv2c_indication_ie(gtp_ies.indication_flags)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_PCO) {std::shared_ptr<gtpv2c_pco_ie> sie(new gtpv2c_pco_ie(gtp_ies.pco)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_ORIGINATING_NODE) {std::shared_ptr<gtpv2c_node_type_ie> sie(new gtpv2c_node_type_ie(gtp_ies.originating_node)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_SENDER_FTEID_FOR_CONTROL_PLANE) {std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(gtp_ies.sender_fteid_for_cp)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_UE_TIME_ZONE) {std::shared_ptr<gtpv2c_ue_time_zone_ie> sie(new gtpv2c_ue_time_zone_ie(gtp_ies.ue_time_zone)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_ULI_TIMESTAMP) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_RAN_NAS_RELEASE_CAUSE) {std::shared_ptr<gtpv2c_ran_nas_cause_ie> sie(new gtpv2c_ran_nas_cause_ie(gtp_ies.ran_nas_release_cause)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_TWAN_IDENTIFIER) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_TWAN_IDENTIFIER_TIMESTAMP) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_MMES4_SGSN_OVERLOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_SGW_OVERLOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_TWAN_EPDG_OVERLOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_WLAN_LOCATION_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_WLAN_LOCATION_TIMESTAMP) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_UE_LOCAL_IP_ADDRESS) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_UE_UDP_PORT) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_EPCO) {std::shared_ptr<gtpv2c_epco_ie> sie(new gtpv2c_epco_ie(gtp_ies.epco)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_UE_TCP_PORT) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_REQUEST_PR_IE_PRIVATE_EXTENSION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
}
//------------------------------------------------------------------------------
gtpv2c_msg::gtpv2c_msg(const gtpv2c_delete_session_response& gtp_ies) : gtpv2c_msg_header() {
ies = {};
set_message_type(GTP_DELETE_SESSION_RESPONSE);
if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_RESPONSE_PR_IE_CAUSE) {std::shared_ptr<gtpv2c_cause_ie> sie(new gtpv2c_cause_ie(gtp_ies.cause)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_RESPONSE_PR_IE_RECOVERY) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_RESPONSE_PR_IE_PCO) {std::shared_ptr<gtpv2c_pco_ie> sie(new gtpv2c_pco_ie(gtp_ies.pco)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_RESPONSE_PR_IE_INDICATION_FLAGS) {std::shared_ptr<gtpv2c_indication_ie> sie(new gtpv2c_indication_ie(gtp_ies.indication_flags)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_RESPONSE_PR_IE_PGW_NODE_LEVEL_LOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_RESPONSE_PR_IE_PGW_APN_LEVEL_LOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_RESPONSE_PR_IE_SGW_NODE_LEVEL_LOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_RESPONSE_PR_IE_PGW_OVERLOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_RESPONSE_PR_IE_SGW_OVERLOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_RESPONSE_PR_IE_EPCO) {std::shared_ptr<gtpv2c_epco_ie> sie(new gtpv2c_epco_ie(gtp_ies.epco)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_DELETE_SESSION_RESPONSE_PR_IE_PRIVATE_EXTENSION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
}
//------------------------------------------------------------------------------
gtpv2c_msg::gtpv2c_msg(const gtpv2c_modify_bearer_request& gtp_ies) : gtpv2c_msg_header() {
ies = {};
set_message_type(GTP_MODIFY_BEARER_REQUEST);
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_MEI) {std::shared_ptr<gtpv2c_mei_ie> sie(new gtpv2c_mei_ie(gtp_ies.mei)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_ULI) {std::shared_ptr<gtpv2c_user_location_information_ie> sie(new gtpv2c_user_location_information_ie(gtp_ies.uli)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_SERVING_NETWORK) {std::shared_ptr<gtpv2c_serving_network_ie> sie(new gtpv2c_serving_network_ie(gtp_ies.serving_network)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_RAT_TYPE) {std::shared_ptr<gtpv2c_rat_type_ie> sie(new gtpv2c_rat_type_ie(gtp_ies.rat_type)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_INDICATION_FLAGS) {std::shared_ptr<gtpv2c_indication_ie> sie(new gtpv2c_indication_ie(gtp_ies.indication_flags)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_SENDER_FTEID_FOR_CONTROL_PLANE) {std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(gtp_ies.sender_fteid_for_cp)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_APN_AMBR) {std::shared_ptr<gtpv2c_aggregate_maximum_bit_rate_ie> sie(new gtpv2c_aggregate_maximum_bit_rate_ie(gtp_ies.apn_ambr)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_DELAY_DOWNLINK_PACKET_NOTIFICATION_REQUEST) {std::shared_ptr<gtpv2c_delay_value_ie> sie(new gtpv2c_delay_value_ie(gtp_ies.delay_dl_packet_notif_req)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_BEARER_CONTEXTS_TO_BE_MODIFIED) {
if (gtp_ies.bearer_contexts_to_be_modified.size() > 0) {
for (auto i : gtp_ies.bearer_contexts_to_be_modified) {
gtpv2c_grouped_ie *gie = new gtpv2c_grouped_ie(GTP_IE_BEARER_CONTEXT);
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_MODIFIED_WITHIN_MODIFY_BEARER_REQUEST_PR_IE_EPS_BEARER_ID) {std::shared_ptr<gtpv2c_eps_bearer_id_ie> sie(new gtpv2c_eps_bearer_id_ie(i.eps_bearer_id)); gie->add_ie(sie);}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_MODIFIED_WITHIN_MODIFY_BEARER_REQUEST_PR_IE_S1_U_ENB_FTEID) {std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s1_u_enb_fteid)); gie->add_ie(sie);}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_MODIFIED_WITHIN_MODIFY_BEARER_REQUEST_PR_IE_S5_S8_U_SGW_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s5_s8_u_sgw_fteid));
sie.get()->tlv.set_instance(1);
gie->add_ie(sie);
}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_MODIFIED_WITHIN_MODIFY_BEARER_REQUEST_PR_IE_S12_RNC_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s12_rnc_fteid));
sie.get()->tlv.set_instance(2);
gie->add_ie(sie);
}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_MODIFIED_WITHIN_MODIFY_BEARER_REQUEST_PR_IE_S4_U_SGSN_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s4_u_sgsn_fteid));
sie.get()->tlv.set_instance(3);
gie->add_ie(sie);
}
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_MODIFIED_WITHIN_MODIFY_BEARER_REQUEST_PR_IE_S11_U_MME_FTEID) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s11_u_mme_fteid));
sie.get()->tlv.set_instance(4);
gie->add_ie(sie);
}
std::shared_ptr<gtpv2c_grouped_ie> sie(gie);
add_ie(sie);
}
}
}
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_BEARER_CONTEXTS_TO_BE_REMOVED) {
if (gtp_ies.bearer_contexts_to_be_removed.size() > 0) {
for (auto i : gtp_ies.bearer_contexts_to_be_removed) {
gtpv2c_grouped_ie *gie = new gtpv2c_grouped_ie(GTP_IE_BEARER_CONTEXT);
gie->tlv.set_instance(1);
if (i.ie_presence_mask & GTPV2C_BEARER_CONTEXT_TO_BE_REMOVED_WITHIN_MODIFY_BEARER_REQUEST_PR_IE_EPS_BEARER_ID) {std::shared_ptr<gtpv2c_eps_bearer_id_ie> sie(new gtpv2c_eps_bearer_id_ie(i.eps_bearer_id)); gie->add_ie(sie);}
std::shared_ptr<gtpv2c_grouped_ie> sie(gie);
add_ie(sie);
}
}
}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_RECOVERY) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_UE_TIME_ZONE) {std::shared_ptr<gtpv2c_ue_time_zone_ie> sie(new gtpv2c_ue_time_zone_ie(gtp_ies.ue_time_zone)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_MME_FQ_CSID) {std::shared_ptr<gtpv2c_fq_csid_ie> sie(new gtpv2c_fq_csid_ie(gtp_ies.mme_fq_csid));add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_SGW_FQ_CSID) {
std::shared_ptr<gtpv2c_fq_csid_ie> sie(new gtpv2c_fq_csid_ie(gtp_ies.sgw_fq_csid));
sie.get()->tlv.set_instance(1);
add_ie(sie);
}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_UCI) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.uci)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_UE_LOCAL_IP_ADDRESS) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_UE_UDP_PORT) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_MME_S4_SGSN_LDN) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_SGW_LDN) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_HENB_LOCAL_IP_ADDRESS) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_HENB_UDP_PORT) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_MME_S4_SGSN_IDENTIFIER) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_CN_OPERATOR_SELECTION_ENTITY) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_PRESENCE_REPORTING_AREA_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_MMES4_SGSN_OVERLOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_SGW_OVERLOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_EPDG_OVERLOAD_CONTROL_INFORMATION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_SERVING_PLMN_RATE_CONTROL) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_MO_EXCEPTION_DATA_COUNTER) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_IMSI) {std::shared_ptr<gtpv2c_imsi_ie> sie(new gtpv2c_imsi_ie(gtp_ies.imsi)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_ULI_FOR_SGW) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_MODIFY_BEARER_REQUEST_PR_IE_PRIVATE_EXTENSION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.xxx)); add_ie(sie);}
}
//------------------------------------------------------------------------------
gtpv2c_msg::gtpv2c_msg(const gtpv2c_modify_bearer_response& gtp_ies) : gtpv2c_msg_header() {
ies = {};
set_message_type(GTP_MODIFY_BEARER_RESPONSE);
/*
cause = {};
msisdn = {};
linked_eps_bearer_id = {};
apn_restriction = {};
pco = {};
bearer_contexts_modified = {};
bearer_contexts_marked_for_removal = {};
pgw_fq_csid = {};
sgw_fq_csid = {};
indication_flags = {};
pdn_connection_charging_id = {};
*/
if (gtp_ies.cause.first) {std::shared_ptr<gtpv2c_cause_ie> sie(new gtpv2c_cause_ie(gtp_ies.cause.second)); add_ie(sie);}
if (gtp_ies.msisdn.first) {std::shared_ptr<gtpv2c_msisdn_ie> sie(new gtpv2c_msisdn_ie(gtp_ies.msisdn.second)); add_ie(sie);}
if (gtp_ies.linked_eps_bearer_id.first) {std::shared_ptr<gtpv2c_eps_bearer_id_ie> sie(new gtpv2c_eps_bearer_id_ie(gtp_ies.linked_eps_bearer_id.second)); add_ie(sie);}
if (gtp_ies.apn_restriction.first) {std::shared_ptr<gtpv2c_apn_restriction_ie> sie(new gtpv2c_apn_restriction_ie(gtp_ies.apn_restriction.second)); add_ie(sie);}
if (gtp_ies.pco.first) {std::shared_ptr<gtpv2c_pco_ie> sie(new gtpv2c_pco_ie(gtp_ies.pco.second)); add_ie(sie);}
if (gtp_ies.pgw_fq_csid.first) {std::shared_ptr<gtpv2c_fq_csid_ie> sie(new gtpv2c_fq_csid_ie(gtp_ies.pgw_fq_csid.second));add_ie(sie);}
if (gtp_ies.sgw_fq_csid.first) {
std::shared_ptr<gtpv2c_fq_csid_ie> sie(new gtpv2c_fq_csid_ie(gtp_ies.sgw_fq_csid.second));
sie.get()->tlv.set_instance(1);
add_ie(sie);
}
if (gtp_ies.indication_flags.first) {std::shared_ptr<gtpv2c_indication_ie> sie(new gtpv2c_indication_ie(gtp_ies.indication_flags.second)); add_ie(sie);}
if (gtp_ies.pdn_connection_charging_id.first) {std::shared_ptr<gtpv2c_charging_id_ie> sie(new gtpv2c_charging_id_ie(gtp_ies.pdn_connection_charging_id.second)); add_ie(sie);}
if (gtp_ies.bearer_contexts_modified.first) {
if (gtp_ies.bearer_contexts_modified.second.size() > 0) {
for (auto i : gtp_ies.bearer_contexts_modified.second) {
gtpv2c_grouped_ie *gie = new gtpv2c_grouped_ie(GTP_IE_BEARER_CONTEXT);
if (i.eps_bearer_id.first) {std::shared_ptr<gtpv2c_eps_bearer_id_ie> sie(new gtpv2c_eps_bearer_id_ie(i.eps_bearer_id.second)); gie->add_ie(sie);}
if (i.cause.first) {std::shared_ptr<gtpv2c_cause_ie> sie(new gtpv2c_cause_ie(i.cause.second)); gie->add_ie(sie);}
if (i.s1_u_sgw_fteid.first) {std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s1_u_sgw_fteid.second)); gie->add_ie(sie);}
if (i.s12_sgw_fteid.first) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s12_sgw_fteid.second));
sie.get()->tlv.set_instance(1);
gie->add_ie(sie);
}
if (i.s4_u_sgw_fteid.first) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s4_u_sgw_fteid.second));
sie.get()->tlv.set_instance(2);
gie->add_ie(sie);
}
if (i.s11_u_sgw_fteid.first) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s11_u_sgw_fteid.second));
sie.get()->tlv.set_instance(3);
gie->add_ie(sie);
}
if (i.charging_id.first) {std::shared_ptr<gtpv2c_charging_id_ie> sie(new gtpv2c_charging_id_ie(i.charging_id.second)); gie->add_ie(sie);}
if (i.bearer_flags.first) {std::shared_ptr<gtpv2c_bearer_flags_ie> sie(new gtpv2c_bearer_flags_ie(i.bearer_flags.second)); gie->add_ie(sie);}
if (i.s11_u_sgw_fteid.first) {
std::shared_ptr<gtpv2c_fully_qualified_teid_ie> sie(new gtpv2c_fully_qualified_teid_ie(i.s11_u_sgw_fteid.second));
sie.get()->tlv.set_instance(6);
gie->add_ie(sie);
}
std::shared_ptr<gtpv2c_grouped_ie> sie(gie);
add_ie(sie);
}
}
}
if (gtp_ies.bearer_contexts_marked_for_removal.first) {
if (gtp_ies.bearer_contexts_marked_for_removal.second.size() > 0) {
for (auto i : gtp_ies.bearer_contexts_marked_for_removal.second) {
gtpv2c_grouped_ie *gie = new gtpv2c_grouped_ie(GTP_IE_BEARER_CONTEXT);
gie->tlv.set_instance(1);
if (i.eps_bearer_id.first) {std::shared_ptr<gtpv2c_eps_bearer_id_ie> sie(new gtpv2c_eps_bearer_id_ie(i.eps_bearer_id.second)); gie->add_ie(sie);}
if (i.cause.first) {std::shared_ptr<gtpv2c_cause_ie> sie(new gtpv2c_cause_ie(i.cause.second)); gie->add_ie(sie);}
std::shared_ptr<gtpv2c_grouped_ie> sie(gie);
add_ie(sie);
}
}
}
}
//------------------------------------------------------------------------------
gtpv2c_msg::gtpv2c_msg(const gtpv2c_release_access_bearers_request& gtp_ies) : gtpv2c_msg_header() {
ies = {};
set_message_type(GTP_RELEASE_ACCESS_BEARERS_REQUEST);
//if (gtp_ies.ie_presence_mask & GTPV2C_RELEASE_ACCESS_BEARERS_REQUEST_PR_IE_LIST_OF_RABS) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.uci)); add_ie(sie);}
if (gtp_ies.originating_node.first) {std::shared_ptr<gtpv2c_node_type_ie> sie(new gtpv2c_node_type_ie(gtp_ies.originating_node.second)); add_ie(sie);}
if (gtp_ies.indication_flags.first) {std::shared_ptr<gtpv2c_indication_ie> sie(new gtpv2c_indication_ie(gtp_ies.indication_flags.second)); add_ie(sie);}
//if (gtp_ies.ie_presence_mask & GTPV2C_RELEASE_ACCESS_BEARERS_REQUEST_PR_IE_PRIVATE_EXTENSION) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.uci)); add_ie(sie);}
}
//------------------------------------------------------------------------------
gtpv2c_msg::gtpv2c_msg(const gtpv2c_release_access_bearers_response& gtp_ies) : gtpv2c_msg_header() {
ies = {};
set_message_type(GTP_RELEASE_ACCESS_BEARERS_RESPONSE);
if (gtp_ies.cause.first) {std::shared_ptr<gtpv2c_cause_ie> sie(new gtpv2c_cause_ie(gtp_ies.cause.second)); add_ie(sie);}
//if (gtp_ies..first) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.uci.second)); add_ie(sie);}
if (gtp_ies.indication_flags.first) {std::shared_ptr<gtpv2c_indication_ie> sie(new gtpv2c_indication_ie(gtp_ies.indication_flags.second)); add_ie(sie);}
//if (gtp_ies..first) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.uci.second)); add_ie(sie);}
//if (gtp_ies.first) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.uci.second)); add_ie(sie);}
//if (gtp_ies.first) {std::shared_ptr<xxx> sie(new xxx(gtp_ies.uci.second)); add_ie(sie);}
}
//------------------------------------------------------------------------------
gtpv2c_msg::gtpv2c_msg(const gtpv2c_echo_request& gtp_ies) : gtpv2c_msg_header() {
ies = {};
set_message_type(GTP_ECHO_REQUEST);
if (gtp_ies.recovery_restart_counter.first) {std::shared_ptr<gtpv2c_recovery_ie> sie(new gtpv2c_recovery_ie(gtp_ies.recovery_restart_counter.second)); add_ie(sie);}
if (gtp_ies.sending_node_features.first) {std::shared_ptr<gtpv2c_node_features_ie> sie(new gtpv2c_node_features_ie(gtp_ies.sending_node_features.second)); add_ie(sie);}
}
//------------------------------------------------------------------------------
gtpv2c_msg::gtpv2c_msg(const gtpv2c_echo_response& gtp_ies) : gtpv2c_msg_header() {
ies = {};
set_message_type(GTP_ECHO_RESPONSE);
if (gtp_ies.recovery_restart_counter.first) {std::shared_ptr<gtpv2c_recovery_ie> sie(new gtpv2c_recovery_ie(gtp_ies.recovery_restart_counter.second)); add_ie(sie);}
if (gtp_ies.sending_node_features.first) {std::shared_ptr<gtpv2c_node_features_ie> sie(new gtpv2c_node_features_ie(gtp_ies.sending_node_features.second)); add_ie(sie);}
}
//------------------------------------------------------------------------------
static const std::vector<std::string> pdn_type_e2str = {"Error", "IPV4", "IPV6", "IPV4V6", "NON_IP"};
const std::string& oai::cn::core::pdn_type_e2string(uint8_t pdn_type) {
return pdn_type_e2str.at(pdn_type);
}
//------------------------------------------------------------------------------
bool oai::cn::core::is_paa_ip_assigned(const paa_t& paa) {
switch (paa.pdn_type.pdn_type) {
case core::PDN_TYPE_E_IPV4:
if (paa.ipv4_address.s_addr) return true;
return false;
break;
case core::PDN_TYPE_E_IPV6:
if (paa.ipv6_address.__in6_u.__u6_addr32[0] |
paa.ipv6_address.__in6_u.__u6_addr32[1] |
paa.ipv6_address.__in6_u.__u6_addr32[2] |
paa.ipv6_address.__in6_u.__u6_addr32[3])
return true;
return false;
break;
case core::PDN_TYPE_E_IPV4V6:
// TODO
if (paa.ipv4_address.s_addr) return true;
if (paa.ipv6_address.__in6_u.__u6_addr32[0] |
paa.ipv6_address.__in6_u.__u6_addr32[1] |
paa.ipv6_address.__in6_u.__u6_addr32[2] |
paa.ipv6_address.__in6_u.__u6_addr32[3])
return true;
return false;
break;
case core::PDN_TYPE_E_NON_IP:
default:
return false;
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file gtpv2c.cpp
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#include "gtpv2c.hpp"
#include <cstdlib>
using namespace oai::cn::proto::gtpv2c;
using namespace oai::cn::core::itti;
using namespace std;
extern boost::asio::io_service io_service;
extern itti_mw *itti_inst;
static std::string string_to_hex(const std::string& input)
{
static const char* const lut = "0123456789ABCDEF";
size_t len = input.length();
std::string output;
output.reserve(2 * len);
for (size_t i = 0; i < len; ++i)
{
const unsigned char c = input[i];
output.push_back(lut[c >> 4]);
output.push_back(lut[c & 15]);
}
return output;
}
//
////------------------------------------------------------------------------------
//void udp_server::fteid_addr2_boost_ip_address(const core::fteid_t & fteid, boost::asio::ip::address & address)
//{
// if ((local_address_.is_v4()) && (fteid.v4)) {
// boost::asio::ip::address_v4 addressv4(ntohl(fteid.ipv4_address.s_addr));
// address = addressv4;
// return;
// }
// if ((local_address_.is_v6()) && (fteid.v6)) {
// boost::asio::ip::address_v6::bytes_type b;
// for (int i = 0 ; i < 16; i++) {
// b[i] = fteid.ipv6_address.__in6_u.__u6_addr8[i];
// }
// boost::asio::ip::address_v6 addressv6(b);
// address = addressv6;
// return;
// }
//}
//------------------------------------------------------------------------------
void udp_server::handle_receive(const boost::system::error_code& error, std::size_t bytes_transferred)
{
if (!error || error == boost::asio::error::message_size) {
//Logger::udp().trace( "udp_server::handle_receive on %s:%d from %s:%d",
// socket_.local_endpoint().address().to_string().c_str(), socket_.local_endpoint().port(),
// remote_endpoint_.address().to_string().c_str(), remote_endpoint_.port());
if (app) {
app->handle_receive(recv_buffer_.data(), bytes_transferred, remote_endpoint_);
} else {
Logger::udp().error( "No upper layer configured for handling UDP packet");
}
start_receive(app);
} else {
Logger::udp().error( "udp_server::handle_receive err=%s/%d: %s", error.category().name(), error.value(), error.message());
}
}
//------------------------------------------------------------------------------
gtpv2c_stack::gtpv2c_stack(const string& ip_address, const unsigned short port_num) :
udp_s(udp_server(io_service, boost::asio::ip::address::from_string(ip_address), port_num)),
udp_s_allocated(udp_server(io_service, boost::asio::ip::address::from_string(ip_address), 0)){
Logger::gtpv2_c().info( "gtpv2c_stack created listening to %s:%d", ip_address.c_str(), port_num);
gtpc_tx_id2seq_num = {};
proc_cleanup_timers = {};
msg_out_retry_timers = {};
pending_procedures = {};
id = 0;
srand (time(NULL));
seq_num = rand() & 0x7FFFFFFF;
restart_counter = 0;
udp_s.start_receive(this);
udp_s_allocated.start_receive(this);
}
//------------------------------------------------------------------------------
uint32_t gtpv2c_stack::get_next_seq_num() {
seq_num++;
if (seq_num & 0x80000000) {
seq_num = 0;
}
return seq_num;
}
//------------------------------------------------------------------------------
void gtpv2c_stack::handle_receive(char* recv_buffer, const std::size_t bytes_transferred, boost::asio::ip::udp::endpoint& remote_endpoint)
{
Logger::gtpv2_c().error( "TODO implement in derived class");
}
//------------------------------------------------------------------------------
bool gtpv2c_stack::check_initial_message_type(const uint8_t initial)
{
switch (initial) {
case GTP_ECHO_REQUEST:
case GTP_CREATE_SESSION_REQUEST:
case GTP_MODIFY_BEARER_REQUEST:
case GTP_DELETE_SESSION_REQUEST:
case GTP_CHANGE_NOTIFICATION_REQUEST:
case GTP_REMOTE_UE_REPORT_NOTIFICATION:
case GTP_MODIFY_BEARER_COMMAND:
case GTP_DELETE_BEARER_COMMAND:
case GTP_BEARER_RESOURCE_COMMAND:
case GTP_CREATE_BEARER_REQUEST:
case GTP_UPDATE_BEARER_REQUEST:
case GTP_DELETE_BEARER_REQUEST:
case GTP_DELETE_PDN_CONNECTION_SET_REQUEST:
case GTP_PGW_DOWNLINK_TRIGGERING_NOTIFICATION:
case GTP_IDENTIFICATION_REQUEST:
case GTP_CONTEXT_REQUEST:
case GTP_FORWARD_RELOCATION_REQUEST:
case GTP_FORWARD_RELOCATION_COMPLETE_NOTIFICATION:
case GTP_FORWARD_ACCESS_CONTEXT_NOTIFICATION:
case GTP_RELOCATION_CANCEL_REQUEST:
case GTP_DETACH_NOTIFICATION:
case GTP_ALERT_MME_NOTIFICATION:
case GTP_UE_ACTIVITY_NOTIFICATION:
case GTP_UE_REGISTRATION_QUERY_REQUEST:
case GTP_CREATE_FORWARDING_TUNNEL_REQUEST:
case GTP_SUSPEND_NOTIFICATION:
case GTP_RESUME_NOTIFICATION:
case GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST:
case GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST:
case GTP_RELEASE_ACCESS_BEARERS_REQUEST:
case GTP_DOWNLINK_DATA_NOTIFICATION:
case GTP_PGW_RESTART_NOTIFICATION:
case GTP_UPDATE_PDN_CONNECTION_SET_REQUEST:
case GTP_MODIFY_ACCESS_BEARERS_REQUEST:
case GTP_MBMS_SESSION_START_REQUEST:
case GTP_MBMS_SESSION_UPDATE_REQUEST:
case GTP_MBMS_SESSION_STOP_REQUEST:
return true;
break;
default:
return false;
}
}
//------------------------------------------------------------------------------
bool gtpv2c_stack::check_triggered_message_type(const uint8_t initial, const uint8_t triggered)
{
Logger::gtpv2_c().info( "check_triggered_message_type GTPV2-C msg type %d/%d", (int)initial, (int)triggered);
switch (initial) {
case GTP_ECHO_REQUEST:
case GTP_CREATE_SESSION_REQUEST:
case GTP_MODIFY_BEARER_REQUEST:
case GTP_DELETE_SESSION_REQUEST:
case GTP_CHANGE_NOTIFICATION_REQUEST:
case GTP_REMOTE_UE_REPORT_NOTIFICATION:
case GTP_MODIFY_BEARER_COMMAND:
case GTP_DELETE_BEARER_COMMAND:
case GTP_BEARER_RESOURCE_COMMAND:
case GTP_CREATE_BEARER_REQUEST:
case GTP_UPDATE_BEARER_REQUEST:
case GTP_DELETE_BEARER_REQUEST:
case GTP_DELETE_PDN_CONNECTION_SET_REQUEST:
case GTP_PGW_DOWNLINK_TRIGGERING_NOTIFICATION:
case GTP_IDENTIFICATION_REQUEST:
case GTP_CONTEXT_REQUEST:
case GTP_FORWARD_RELOCATION_REQUEST:
case GTP_FORWARD_RELOCATION_COMPLETE_NOTIFICATION:
case GTP_FORWARD_ACCESS_CONTEXT_NOTIFICATION:
case GTP_RELOCATION_CANCEL_REQUEST:
case GTP_DETACH_NOTIFICATION:
case GTP_ALERT_MME_NOTIFICATION:
case GTP_UE_ACTIVITY_NOTIFICATION:
case GTP_UE_REGISTRATION_QUERY_REQUEST:
case GTP_CREATE_FORWARDING_TUNNEL_REQUEST:
case GTP_SUSPEND_NOTIFICATION:
case GTP_RESUME_NOTIFICATION:
case GTP_CREATE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST:
case GTP_DELETE_INDIRECT_DATA_FORWARDING_TUNNEL_REQUEST:
case GTP_RELEASE_ACCESS_BEARERS_REQUEST:
case GTP_DOWNLINK_DATA_NOTIFICATION:
case GTP_PGW_RESTART_NOTIFICATION:
case GTP_UPDATE_PDN_CONNECTION_SET_REQUEST:
case GTP_MODIFY_ACCESS_BEARERS_REQUEST:
case GTP_MBMS_SESSION_START_REQUEST:
case GTP_MBMS_SESSION_UPDATE_REQUEST:
case GTP_MBMS_SESSION_STOP_REQUEST:
if (triggered == (initial+1)) return true;
break;
default:
if (triggered == GTP_VERSION_NOT_SUPPORTED_INDICATION) return true;
}
switch (triggered) {
case GTP_CREATE_BEARER_REQUEST:
case GTP_UPDATE_BEARER_REQUEST:
case GTP_DELETE_BEARER_REQUEST:
// TODO refine this
return true;
break;
default:
return false;
}
}
//------------------------------------------------------------------------------
void gtpv2c_stack::start_msg_retry_timer(gtpv2c_procedure& p, uint32_t time_out_milli_seconds, const task_id_t& task_id, const uint32_t& seq_num)
{
if (!p.retry_timer_id) {
p.retry_timer_id = itti_inst->timer_setup (time_out_milli_seconds/1000, time_out_milli_seconds%1000, task_id);
msg_out_retry_timers.insert(std::pair<core::itti::timer_id_t, uint32_t>(p.retry_timer_id, seq_num));
//Logger::gtpv2_c().trace( "Started Msg retry timer %d, proc %" PRId64", seq %d",p.retry_timer_id, p.gtpc_tx_id, seq_num);
} else {
Logger::gtpv2_c().error( "Try to overwrite Msg retry timer %d, proc %" PRId64", seq %d!",p.retry_timer_id, p.gtpc_tx_id, seq_num);
}
}
//------------------------------------------------------------------------------
void gtpv2c_stack::stop_msg_retry_timer(gtpv2c_procedure& p)
{
if (p.retry_timer_id) {
itti_inst->timer_remove(p.retry_timer_id);
msg_out_retry_timers.erase(p.retry_timer_id);
//Logger::gtpv2_c().trace( "Stopped Msg retry timer %d, proc %" PRId64", seq %d",p.retry_timer_id, p.gtpc_tx_id, p.retry_msg->get_sequence_number());
p.retry_timer_id = 0;
}
}
//------------------------------------------------------------------------------
void gtpv2c_stack::stop_msg_retry_timer(oai::cn::core::itti::timer_id_t& t)
{
itti_inst->timer_remove(t);
msg_out_retry_timers.erase(t);
//Logger::gtpv2_c().trace( "Stopped Msg retry timer %d",t);
}
//------------------------------------------------------------------------------
void gtpv2c_stack::start_proc_cleanup_timer(gtpv2c_procedure& p, uint32_t time_out_milli_seconds, const task_id_t& task_id, const uint32_t& seq_num)
{
if (!p.proc_cleanup_timer_id) {
p.proc_cleanup_timer_id = itti_inst->timer_setup (time_out_milli_seconds/1000, time_out_milli_seconds%1000, task_id);
proc_cleanup_timers.insert(std::pair<core::itti::timer_id_t, uint32_t>(p.proc_cleanup_timer_id, seq_num));
//Logger::gtpv2_c().trace( "Started proc cleanup timer %d, proc %" PRId64" t-out %" PRIu32" ms",p.proc_cleanup_timer_id,p.gtpc_tx_id, time_out_milli_seconds);
} else {
Logger::gtpv2_c().error( "Try to overwrite proc cleanup timer %d, proc %" PRId64" t-out %" PRIu32" ms",p.proc_cleanup_timer_id,p.gtpc_tx_id, time_out_milli_seconds);
}
}
//------------------------------------------------------------------------------
void gtpv2c_stack::stop_proc_cleanup_timer(gtpv2c_procedure& p)
{
itti_inst->timer_remove(p.proc_cleanup_timer_id);
//Logger::gtpv2_c().trace( "Stopped proc cleanup timer %d, proc %" PRId64"",p.proc_cleanup_timer_id, p.gtpc_tx_id);
msg_out_retry_timers.erase(p.proc_cleanup_timer_id);
p.proc_cleanup_timer_id = 0;
}
//------------------------------------------------------------------------------
void gtpv2c_stack::handle_receive_message_cb(const gtpv2c_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint, const task_id_t& task_id, bool &error, uint64_t& gtpc_tx_id)
{
gtpc_tx_id = 0;
error = true;
std::map<uint32_t , gtpv2c_procedure>::iterator it;
it = pending_procedures.find(msg.get_sequence_number());
if (it == pending_procedures.end()) {
if (gtpv2c_stack::check_initial_message_type(msg.get_message_type())) {
gtpv2c_procedure proc = {};
proc.gtpc_tx_id = generate_gtpc_tx_id();
proc.initial_msg_type = msg.get_message_type();
// TODO later 13.3 Detection and handling of requests which have timed out at the originating entity
// if (msg_has_timestamp()) {
// start_proc_cleanup_timer(proc, (N3+1) x T3, task_id, msg.get_sequence_number());
// } else
start_proc_cleanup_timer(proc, GTPV2C_PROC_TIME_OUT_MS, task_id, msg.get_sequence_number());
pending_procedures.insert(std::pair<uint32_t, gtpv2c_procedure>(msg.get_sequence_number(), proc));
gtpc_tx_id2seq_num.insert(std::pair<uint64_t, uint32_t>(proc.gtpc_tx_id, msg.get_sequence_number()));
error = false;
gtpc_tx_id = proc.gtpc_tx_id;
Logger::gtpv2_c().info( "Received Initial GTPV2-C msg type %d, seq %d, proc %" PRId64"", msg.get_message_type(), msg.get_sequence_number(), proc.gtpc_tx_id);
} else {
Logger::gtpv2_c().info( "Failed to check Initial message type, Silently discarding GTPV2-C msg type %d, seq %d", msg.get_message_type(), msg.get_sequence_number());
error = true;
}
return;
} else {
// Logger::gtpv2_c().info( "gtpv2c_procedure retry_timer_id %d", it->second.retry_timer_id);
// Logger::gtpv2_c().info( "gtpv2c_procedure proc_cleanup_timer_id %d", it->second.proc_cleanup_timer_id);
// Logger::gtpv2_c().info( "gtpv2c_procedure gtpc_tx_id %ld", it->second.gtpc_tx_id);
// Logger::gtpv2_c().info( "gtpv2c_procedure initial_msg_type %d", it->second.initial_msg_type);
// Logger::gtpv2_c().info( "gtpv2c_procedure triggered_msg_type %d", it->second.triggered_msg_type);
// Logger::gtpv2_c().info( "gtpv2c_procedure retry_count %d", it->second.retry_count);
uint8_t check_initial_msg_type = it->second.triggered_msg_type;
if (!it->second.triggered_msg_type) {
check_initial_msg_type = it->second.initial_msg_type;
}
if (gtpv2c_stack::check_triggered_message_type(check_initial_msg_type, msg.get_message_type())) {
if (!it->second.triggered_msg_type) {
it->second.triggered_msg_type = msg.get_message_type();
}
error = false;
gtpc_tx_id = it->second.gtpc_tx_id;
if (it->second.retry_timer_id) {
stop_msg_retry_timer(it->second);
}
Logger::gtpv2_c().info( "Received Triggered GTPV2-C msg type %d, seq %d, proc %" PRId64"", msg.get_message_type(), msg.get_sequence_number(), gtpc_tx_id);
} else {
Logger::gtpv2_c().info( "Failed to check Triggered message type, Silently discarding GTPV2-C msg type %d, seq %d", msg.get_message_type(), msg.get_sequence_number());
error = true;
}
}
}
//------------------------------------------------------------------------------
uint32_t gtpv2c_stack::send_initial_message(const boost::asio::ip::udp::endpoint& dest, const gtpv2c_echo_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id)
{
std::ostringstream oss(std::ostringstream::binary);
gtpv2c_msg msg(gtp_ies);
msg.set_sequence_number(get_next_seq_num());
msg.dump_to(oss);
//std::cout << string_to_hex(oss.str()) << std::endl;
//std::cout << std::hex << "msg length 0x" << msg.get_message_length() << "msg seqnum 0x" << msg.get_sequence_number() << std::endl;
boost::shared_ptr<std::string> sm = boost::shared_ptr<std::string>(new std::string(oss.str()));
Logger::gtpv2_c().trace( "Sending %s, seq %d, teid " TEID_FMT " ", gtp_ies.get_msg_name(), msg.get_sequence_number());
gtpv2c_procedure proc = {};
proc.initial_msg_type = msg.get_message_type();
proc.gtpc_tx_id = gtp_tx_id;
proc.retry_msg = std::make_shared<gtpv2c_msg>(msg);
proc.remote_endpoint = dest;
start_msg_retry_timer(proc, GTPV2C_T3_RESPONSE_MS, task_id, msg.get_sequence_number());
start_proc_cleanup_timer(proc, GTPV2C_PROC_TIME_OUT_MS, task_id, msg.get_sequence_number());
pending_procedures.insert(std::pair<uint32_t, gtpv2c_procedure>(msg.get_sequence_number(), proc));
gtpc_tx_id2seq_num.insert(std::pair<uint64_t, uint32_t>(proc.gtpc_tx_id, msg.get_sequence_number()));
udp_s_allocated.async_send_to(sm, dest);
return msg.get_sequence_number();
}
//------------------------------------------------------------------------------
uint32_t gtpv2c_stack::send_initial_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_create_session_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id)
{
std::ostringstream oss(std::ostringstream::binary);
gtpv2c_msg msg(gtp_ies);
msg.set_teid(teid);
msg.set_sequence_number(get_next_seq_num());
msg.dump_to(oss);
//std::cout << string_to_hex(oss.str()) << std::endl;
//std::cout << std::hex << "msg length 0x" << msg.get_message_length() << "msg seqnum 0x" << msg.get_sequence_number() << std::endl;
boost::shared_ptr<std::string> sm = boost::shared_ptr<std::string>(new std::string(oss.str()));
Logger::gtpv2_c().trace( "Sending %s, seq %d, teid " TEID_FMT " ", gtp_ies.get_msg_name(), msg.get_sequence_number());
gtpv2c_procedure proc = {};
proc.initial_msg_type = msg.get_message_type();
proc.gtpc_tx_id = gtp_tx_id;
proc.retry_msg = std::make_shared<gtpv2c_msg>(msg);
proc.remote_endpoint = dest;
start_msg_retry_timer(proc, GTPV2C_T3_RESPONSE_MS, task_id, msg.get_sequence_number());
start_proc_cleanup_timer(proc, GTPV2C_PROC_TIME_OUT_MS, task_id, msg.get_sequence_number());
pending_procedures.insert(std::pair<uint32_t, gtpv2c_procedure>(msg.get_sequence_number(), proc));
gtpc_tx_id2seq_num.insert(std::pair<uint64_t, uint32_t>(proc.gtpc_tx_id, msg.get_sequence_number()));
udp_s_allocated.async_send_to(sm, dest);
return msg.get_sequence_number();
}
//------------------------------------------------------------------------------
uint32_t gtpv2c_stack::send_initial_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_delete_session_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id)
{
std::ostringstream oss(std::ostringstream::binary);
gtpv2c_msg msg(gtp_ies);
msg.set_teid(teid);
msg.set_sequence_number(get_next_seq_num());
msg.dump_to(oss);
boost::shared_ptr<std::string> sm = boost::shared_ptr<std::string>(new std::string(oss.str()));
Logger::gtpv2_c().trace( "Sending %s, seq %d", gtp_ies.get_msg_name(), msg.get_sequence_number());
gtpv2c_procedure proc = {};
proc.initial_msg_type = msg.get_message_type();
proc.gtpc_tx_id = gtp_tx_id;
proc.retry_msg = std::make_shared<gtpv2c_msg>(msg);
proc.remote_endpoint = dest;
start_msg_retry_timer(proc, GTPV2C_T3_RESPONSE_MS, task_id, msg.get_sequence_number());
start_proc_cleanup_timer(proc, GTPV2C_PROC_TIME_OUT_MS, task_id, msg.get_sequence_number());
pending_procedures.insert(std::pair<uint32_t, gtpv2c_procedure>(msg.get_sequence_number(), proc));
gtpc_tx_id2seq_num.insert(std::pair<uint64_t, uint32_t>(proc.gtpc_tx_id, msg.get_sequence_number()));
udp_s_allocated.async_send_to(sm, dest);
return msg.get_sequence_number();
}
//------------------------------------------------------------------------------
uint32_t gtpv2c_stack::send_initial_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_modify_bearer_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id)
{
std::ostringstream oss(std::ostringstream::binary);
gtpv2c_msg msg(gtp_ies);
msg.set_teid(teid);
msg.set_sequence_number(get_next_seq_num());
msg.dump_to(oss);
boost::shared_ptr<std::string> sm = boost::shared_ptr<std::string>(new std::string(oss.str()));
Logger::gtpv2_c().trace( "Sending %s, seq %d", gtp_ies.get_msg_name(), msg.get_sequence_number());
gtpv2c_procedure proc = {};
proc.initial_msg_type = msg.get_message_type();
proc.gtpc_tx_id = gtp_tx_id;
proc.retry_msg = std::make_shared<gtpv2c_msg>(msg);
proc.remote_endpoint = dest;
start_msg_retry_timer(proc, GTPV2C_T3_RESPONSE_MS, task_id, msg.get_sequence_number());
start_proc_cleanup_timer(proc, GTPV2C_PROC_TIME_OUT_MS, task_id, msg.get_sequence_number());
pending_procedures.insert(std::pair<uint32_t, gtpv2c_procedure>(msg.get_sequence_number(), proc));
gtpc_tx_id2seq_num.insert(std::pair<uint64_t, uint32_t>(proc.gtpc_tx_id, msg.get_sequence_number()));
udp_s_allocated.async_send_to(sm, dest);
return msg.get_sequence_number();
}
//------------------------------------------------------------------------------
uint32_t gtpv2c_stack::send_initial_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_release_access_bearers_request& gtp_ies, const task_id_t& task_id, const uint64_t gtp_tx_id)
{
std::ostringstream oss(std::ostringstream::binary);
gtpv2c_msg msg(gtp_ies);
msg.set_teid(teid);
msg.set_sequence_number(get_next_seq_num());
msg.dump_to(oss);
boost::shared_ptr<std::string> sm = boost::shared_ptr<std::string>(new std::string(oss.str()));
Logger::gtpv2_c().trace( "Sending %s, seq %d", gtp_ies.get_msg_name(), msg.get_sequence_number());
gtpv2c_procedure proc = {};
proc.initial_msg_type = msg.get_message_type();
proc.gtpc_tx_id = gtp_tx_id;
proc.retry_msg = std::make_shared<gtpv2c_msg>(msg);
proc.remote_endpoint = dest;
start_msg_retry_timer(proc, GTPV2C_T3_RESPONSE_MS, task_id, msg.get_sequence_number());
start_proc_cleanup_timer(proc, GTPV2C_PROC_TIME_OUT_MS, task_id, msg.get_sequence_number());
pending_procedures.insert(std::pair<uint32_t, gtpv2c_procedure>(msg.get_sequence_number(), proc));
gtpc_tx_id2seq_num.insert(std::pair<uint64_t, uint32_t>(proc.gtpc_tx_id, msg.get_sequence_number()));
start_msg_retry_timer(proc, GTPV2C_T3_RESPONSE_MS, task_id, msg.get_sequence_number());
udp_s_allocated.async_send_to(sm, dest);
return msg.get_sequence_number();
}
//------------------------------------------------------------------------------
void gtpv2c_stack::send_triggered_message(const boost::asio::ip::udp::endpoint& dest, const gtpv2c_echo_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a)
{
std::map<uint64_t , uint32_t>::iterator it;
it = gtpc_tx_id2seq_num.find(gtp_tx_id);
if (it != gtpc_tx_id2seq_num.end()) {
std::ostringstream oss(std::ostringstream::binary);
gtpv2c_msg msg(gtp_ies);
msg.set_sequence_number(it->second);
msg.dump_to(oss);
boost::shared_ptr<std::string> sm = boost::shared_ptr<std::string>(new std::string(oss.str()));
Logger::gtpv2_c().trace( "Sending %s, seq %d", gtp_ies.get_msg_name(), msg.get_sequence_number());
udp_s.async_send_to(sm, dest);
if (a == DELETE_TX) {
std::map<uint32_t , gtpv2c_procedure>::iterator it_proc = pending_procedures.find(it->second);
if (it_proc != pending_procedures.end()) {
stop_proc_cleanup_timer(it_proc->second);
pending_procedures.erase(it_proc);
}
gtpc_tx_id2seq_num.erase(it);
}
} else {
Logger::gtpv2_c().error( "Sending %s, gtp_tx_id %ld proc not found, discarded!", gtp_ies.get_msg_name(), gtp_tx_id);
}
}
//------------------------------------------------------------------------------
void gtpv2c_stack::send_triggered_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_create_session_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a)
{
std::map<uint64_t , uint32_t>::iterator it;
it = gtpc_tx_id2seq_num.find(gtp_tx_id);
if (it != gtpc_tx_id2seq_num.end()) {
std::ostringstream oss(std::ostringstream::binary);
gtpv2c_msg msg(gtp_ies);
msg.set_teid(teid);
msg.set_sequence_number(it->second);
msg.dump_to(oss);
boost::shared_ptr<std::string> sm = boost::shared_ptr<std::string>(new std::string(oss.str()));
Logger::gtpv2_c().trace( "Sending %s, seq %d", gtp_ies.get_msg_name(), msg.get_sequence_number());
udp_s.async_send_to(sm, dest);
if (a == DELETE_TX) {
std::map<uint32_t , gtpv2c_procedure>::iterator it_proc = pending_procedures.find(it->second);
if (it_proc != pending_procedures.end()) {
stop_proc_cleanup_timer(it_proc->second);
pending_procedures.erase(it_proc);
}
gtpc_tx_id2seq_num.erase(it);
}
} else {
Logger::gtpv2_c().error( "Sending %s, gtp_tx_id %ld proc not found, discarded!", gtp_ies.get_msg_name(), gtp_tx_id);
}
}
//------------------------------------------------------------------------------
void gtpv2c_stack::send_triggered_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_delete_session_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a)
{
std::map<uint64_t , uint32_t>::iterator it;
it = gtpc_tx_id2seq_num.find(gtp_tx_id);
if (it != gtpc_tx_id2seq_num.end()) {
std::ostringstream oss(std::ostringstream::binary);
gtpv2c_msg msg(gtp_ies);
msg.set_teid(teid);
msg.set_sequence_number(it->second);
msg.dump_to(oss);
boost::shared_ptr<std::string> sm = boost::shared_ptr<std::string>(new std::string(oss.str()));
Logger::gtpv2_c().trace( "Sending %s, seq %d", gtp_ies.get_msg_name(), msg.get_sequence_number());
udp_s.async_send_to(sm, dest);
if (a == DELETE_TX) {
std::map<uint32_t , gtpv2c_procedure>::iterator it_proc = pending_procedures.find(it->second);
if (it_proc != pending_procedures.end()) {
stop_proc_cleanup_timer(it_proc->second);
pending_procedures.erase(it_proc);
}
gtpc_tx_id2seq_num.erase(it);
}
} else {
Logger::gtpv2_c().error( "Sending %s, gtp_tx_id %ld proc not found, discarded!", gtp_ies.get_msg_name(), gtp_tx_id);
}
}
//------------------------------------------------------------------------------
void gtpv2c_stack::send_triggered_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_modify_bearer_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a)
{
std::map<uint64_t , uint32_t>::iterator it;
it = gtpc_tx_id2seq_num.find(gtp_tx_id);
if (it != gtpc_tx_id2seq_num.end()) {
std::ostringstream oss(std::ostringstream::binary);
gtpv2c_msg msg(gtp_ies);
msg.set_teid(teid);
msg.set_sequence_number(it->second);
msg.dump_to(oss);
boost::shared_ptr<std::string> sm = boost::shared_ptr<std::string>(new std::string(oss.str()));
Logger::gtpv2_c().trace( "Sending %s, seq %d", gtp_ies.get_msg_name(), msg.get_sequence_number());
udp_s.async_send_to(sm, dest);
if (a == DELETE_TX) {
std::map<uint32_t , gtpv2c_procedure>::iterator it_proc = pending_procedures.find(it->second);
if (it_proc != pending_procedures.end()) {
stop_proc_cleanup_timer(it_proc->second);
pending_procedures.erase(it_proc);
}
gtpc_tx_id2seq_num.erase(it);
}
} else {
Logger::gtpv2_c().error( "Sending %s, gtp_tx_id %ld proc not found, discarded!", gtp_ies.get_msg_name(), gtp_tx_id);
}
}
//------------------------------------------------------------------------------
void gtpv2c_stack::send_triggered_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_release_access_bearers_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a)
{
std::map<uint64_t , uint32_t>::iterator it;
it = gtpc_tx_id2seq_num.find(gtp_tx_id);
if (it != gtpc_tx_id2seq_num.end()) {
std::ostringstream oss(std::ostringstream::binary);
gtpv2c_msg msg(gtp_ies);
msg.set_teid(teid);
msg.set_sequence_number(it->second);
msg.dump_to(oss);
boost::shared_ptr<std::string> sm = boost::shared_ptr<std::string>(new std::string(oss.str()));
Logger::gtpv2_c().trace( "Sending %s, seq %d", gtp_ies.get_msg_name(), msg.get_sequence_number());
udp_s.async_send_to(sm, dest);
if (a == DELETE_TX) {
std::map<uint32_t , gtpv2c_procedure>::iterator it_proc = pending_procedures.find(it->second);
if (it_proc != pending_procedures.end()) {
stop_proc_cleanup_timer(it_proc->second);
pending_procedures.erase(it_proc);
}
gtpc_tx_id2seq_num.erase(it);
}
} else {
Logger::gtpv2_c().error( "Sending %s, gtp_tx_id %ld proc not found, discarded!", gtp_ies.get_msg_name(), gtp_tx_id);
}
}
//------------------------------------------------------------------------------
void gtpv2c_stack::notify_ul_error(const gtpv2c_procedure& p, const core::cause_value_e cause)
{
Logger::gtpv2_c().trace( "notify_ul_error proc %" PRId64" cause %d", p.gtpc_tx_id, cause);
}
//------------------------------------------------------------------------------
void gtpv2c_stack::time_out_event(const uint32_t timer_id, const task_id_t& task_id, bool &handled)
{
handled = false;
std::map<core::itti::timer_id_t, uint32_t>::iterator it = msg_out_retry_timers.find(timer_id);
if (it != msg_out_retry_timers.end()) {
std::map<uint32_t , gtpv2c_procedure>::iterator it_proc = pending_procedures.find(it->second);
msg_out_retry_timers.erase(it);
handled = true;
if (it_proc != pending_procedures.end()) {
if (it_proc->second.retry_count < GTPV2C_N3_REQUESTS) {
it_proc->second.retry_count++;
start_msg_retry_timer(it_proc->second, GTPV2C_T3_RESPONSE_MS, task_id, it_proc->second.retry_msg->get_sequence_number());
// send again message
Logger::gtpv2_c().trace( "Retry %d Sending msg type %d, seq %d",
it_proc->second.retry_count, it_proc->second.retry_msg->get_message_type(), it_proc->second.retry_msg->get_sequence_number());
std::ostringstream oss(std::ostringstream::binary);
it_proc->second.retry_msg->dump_to(oss);
boost::shared_ptr<std::string> sm = boost::shared_ptr<std::string>(new std::string(oss.str()));
udp_s.async_send_to(sm, it_proc->second.remote_endpoint);
} else {
// abort procedure
notify_ul_error(it_proc->second, core::cause_value_e::REMOTE_PEER_NOT_RESPONDING);
}
}
} else {
it = proc_cleanup_timers.find(timer_id);
if (it != proc_cleanup_timers.end()) {
std::map<uint32_t , gtpv2c_procedure>::iterator it_proc = pending_procedures.find(it->second);
proc_cleanup_timers.erase(it);
handled = true;
if (it_proc != pending_procedures.end()) {
it_proc->second.proc_cleanup_timer_id = 0;
Logger::gtpv2_c().trace( "Delete proc %" PRId64" Retry %d seq %d timer id %u",
it_proc->second.gtpc_tx_id, it_proc->second.retry_count, it_proc->first, timer_id);
pending_procedures.erase(it_proc);
}
}
}
}
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file gtpv2c.hpp
\brief
\author Lionel Gauthier
\company Eurecom
\email: lionel.gauthier@eurecom.fr
*/
#ifndef FILE_GTPV2C_HPP_SEEN
#define FILE_GTPV2C_HPP_SEEN
#include "3gpp_29.274.hpp"
#include "itti.hpp"
#include "msg_gtpv2c.hpp"
#include "uint_generator.hpp"
#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ip/address.hpp>
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
namespace oai::cn::proto::gtpv2c {
class gtpv2c_procedure {
public:
std::shared_ptr<gtpv2c_msg> retry_msg;
boost::asio::ip::udp::endpoint remote_endpoint;
core::itti::timer_id_t retry_timer_id;
core::itti::timer_id_t proc_cleanup_timer_id;
uint64_t gtpc_tx_id;
uint8_t initial_msg_type; // sent or received
uint8_t triggered_msg_type; // sent or received
uint8_t retry_count;
// Could add customized N3, and customized T3:
// T3-RESPONSE timer and N3-REQUESTS counter setting is implementation
// dependent. That is, the timers and counters may be configurable per procedure. Multileg communications (e.g. Create
// Session Requests and Responses) however require longer timer values and possibly a higher number of retransmission
// attempts compared to single leg communication.
gtpv2c_procedure() :
retry_msg(),
remote_endpoint(),
retry_timer_id(0),
proc_cleanup_timer_id(0),
gtpc_tx_id(0),
initial_msg_type(0),
triggered_msg_type(0),
retry_count(0) {}
gtpv2c_procedure(const gtpv2c_procedure& p) :
retry_msg(p.retry_msg),
remote_endpoint(p.remote_endpoint),
retry_timer_id(p.retry_timer_id),
proc_cleanup_timer_id(p.proc_cleanup_timer_id),
gtpc_tx_id(p.gtpc_tx_id),
initial_msg_type(p.initial_msg_type),
triggered_msg_type(p.triggered_msg_type),
retry_count(p.retry_count) {}
};
class gtpv2c_stack;
class udp_server
{
public:
udp_server(boost::asio::io_service& io_service, boost::asio::ip::address address, const unsigned short port_num)
: app(nullptr), local_address_(address), socket_(io_service, boost::asio::ip::udp::endpoint(address, port_num))
{
boost::asio::socket_base::reuse_address option(true);
socket_.set_option(option);
Logger::udp().debug( "udp_server::udp_server(%s:%d) for GTPv2-C", address.to_string().c_str(), port_num);
}
void async_send_to(boost::shared_ptr<std::string> message, boost::asio::ip::udp::endpoint remote_endpoint)
{
Logger::udp().trace( "udp_server::async_send_to(%s:%d) %d bytes", remote_endpoint.address().to_string().c_str(), remote_endpoint.port(), message.get()->size());
socket_.async_send_to(boost::asio::buffer(*message), remote_endpoint,
boost::bind(&udp_server::handle_send, this, message,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
void start_receive(gtpv2c_stack * gtp_stack)
{
app = gtp_stack;
socket_.async_receive_from(
boost::asio::buffer(recv_buffer_), remote_endpoint_,
boost::bind(&udp_server::handle_receive, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
}
protected:
void handle_receive(const boost::system::error_code& error, std::size_t bytes_transferred);
void handle_send(boost::shared_ptr<std::string> /*message*/,
const boost::system::error_code& /*error*/,
std::size_t /*bytes_transferred*/)
{
}
gtpv2c_stack* app;
boost::asio::ip::udp::socket socket_;
boost::asio::ip::udp::endpoint remote_endpoint_;
boost::asio::ip::address local_address_;
boost::array<char, 4096> recv_buffer_;
};
enum gtpv2c_transaction_action {
DELETE_TX = 0,
CONTINUE_TX
};
class gtpv2c_stack {
#define GTPV2C_T3_RESPONSE_MS 1000
#define GTPV2C_N3_REQUESTS 3
#define GTPV2C_PROC_TIME_OUT_MS ((GTPV2C_T3_RESPONSE_MS) * (GTPV2C_N3_REQUESTS + 1) + 1000)
protected:
uint32_t id;
udp_server udp_s;
udp_server udp_s_allocated;
// seems no need for std::atomic_uint32_t
uint32_t seq_num;
uint32_t restart_counter;
std::map<uint64_t, uint32_t> gtpc_tx_id2seq_num;
std::map<core::itti::timer_id_t, uint32_t> proc_cleanup_timers;
std::map<core::itti::timer_id_t, uint32_t> msg_out_retry_timers;
std::map<uint32_t , gtpv2c_procedure> pending_procedures;
boost::array<char, 4096> send_buffer;
static const char* msg_type2cstr[256];
uint32_t get_next_seq_num();
static uint64_t generate_gtpc_tx_id() {
return oai::cn::util::uint_uid_generator<uint64_t>::get_instance().get_uid();
}
static bool check_initial_message_type(const uint8_t initial);
static bool check_triggered_message_type(const uint8_t initial, const uint8_t triggered);
void start_proc_cleanup_timer(gtpv2c_procedure& p, uint32_t time_out_milli_seconds, const core::itti::task_id_t& task_id, const uint32_t& seq_num);
void start_msg_retry_timer(gtpv2c_procedure& p, uint32_t time_out_milli_seconds, const core::itti::task_id_t& task_id, const uint32_t& seq_num);
void stop_msg_retry_timer(gtpv2c_procedure& p);
void stop_msg_retry_timer(core::itti::timer_id_t& t);
void stop_proc_cleanup_timer(gtpv2c_procedure& p);
void notify_ul_error(const gtpv2c_procedure& p, const oai::cn::core::cause_value_e cause);
public:
static const uint8_t version = 2;
gtpv2c_stack(const std::string& ip_address, const unsigned short port_num);
virtual void handle_receive(char* recv_buffer, const std::size_t bytes_transferred, boost::asio::ip::udp::endpoint& remote_endpoint);
void handle_receive_message_cb(const gtpv2c_msg& msg, const boost::asio::ip::udp::endpoint& remote_endpoint, const core::itti::task_id_t& task_id, bool& error, uint64_t& gtpc_tx_id);
// Path mangement messages
virtual uint32_t send_initial_message(const boost::asio::ip::udp::endpoint& dest, const gtpv2c_echo_request& gtp_ies, const core::itti::task_id_t& task_id, const uint64_t gtp_tx_id);
virtual void send_triggered_message(const boost::asio::ip::udp::endpoint& dest, const gtpv2c_echo_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a = DELETE_TX);
// Tunnel management messages
virtual uint32_t send_initial_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_create_session_request& gtp_ies, const core::itti::task_id_t& task_id, const uint64_t gtp_tx_id);
virtual uint32_t send_initial_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_delete_session_request& gtp_ies, const core::itti::task_id_t& task_id, const uint64_t gtp_tx_id);
virtual uint32_t send_initial_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_modify_bearer_request& gtp_ies, const core::itti::task_id_t& task_id, const uint64_t gtp_tx_id);
virtual uint32_t send_initial_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_release_access_bearers_request& gtp_ies, const core::itti::task_id_t& task_id, const uint64_t gtp_tx_id);
virtual void send_triggered_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_create_session_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a = DELETE_TX);
virtual void send_triggered_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_delete_session_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a = DELETE_TX);
virtual void send_triggered_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_modify_bearer_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a = DELETE_TX);
virtual void send_triggered_message(const boost::asio::ip::udp::endpoint& dest, const teid_t teid, const gtpv2c_release_access_bearers_response& gtp_ies, const uint64_t gtp_tx_id, const gtpv2c_transaction_action& a = DELETE_TX);
void time_out_event(const uint32_t timer_id, const core::itti::task_id_t& task_id, bool &error);
};
} // namespace gtpv2c
#endif /* FILE_GTPV2C_HPP_SEEN */
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment