use crate::error::PfcpError;
pub mod access_availability_control_information;
pub mod access_availability_information;
pub mod access_availability_report;
pub mod activate_predefined_rules;
pub mod activation_time;
pub mod add_mbs_unicast_parameters;
pub mod additional_monitoring_time;
pub mod additional_usage_reports_information;
pub mod aggregated_urr_id;
pub mod aggregated_urrs;
pub mod alternative_smf_ip_address;
pub mod apn_dnn;
pub mod application_detection_information;
pub mod application_id;
pub mod application_ids_pfds;
pub mod application_instance_id;
pub mod apply_action;
pub mod area_session_id;
pub mod atsss_control_parameters;
pub mod atsss_ll_control_information;
pub mod atsss_ll_information;
pub mod atsss_ll_parameters;
pub mod average_packet_delay;
pub mod averaging_window;
pub mod bar;
pub mod bar_id;
pub mod bridge_management_information_container;
pub mod c_tag;
pub mod called_number;
pub mod calling_number;
pub mod cause;
pub mod clock_drift_control_information;
pub mod clock_drift_report;
pub mod configured_time_domain;
pub mod cp_function_features;
pub mod cp_ip_address;
pub mod cp_pfcp_entity_ip_address;
pub mod create_bar;
pub mod create_bridge_info_for_tsc;
pub mod create_far;
pub mod create_mar;
pub mod create_pdr;
pub mod create_qer;
pub mod create_srr;
pub mod create_traffic_endpoint;
pub mod create_urr;
pub mod created_bridge_info_for_tsc;
pub mod created_l2tp_session;
pub mod created_pdr;
pub mod created_traffic_endpoint;
pub mod cumulative_rate_ratio_measurement;
pub mod cumulative_rate_ratio_threshold;
pub mod data_network_access_identifier;
pub mod data_status;
pub mod deactivate_predefined_rules;
pub mod deactivation_time;
pub mod destination_interface;
pub mod direct_reporting_information;
pub mod dl_buffering_duration;
pub mod dl_buffering_suggested_packet_count;
pub mod dl_data_packets_size;
pub mod dl_flow_level_marking;
pub mod dl_periodicity;
pub mod dns_query_response_filter;
pub mod dns_server_address;
pub mod downlink_data_notification_delay;
pub mod downlink_data_report;
pub mod downlink_data_service_information;
pub mod dropped_dl_traffic_threshold;
pub mod dscp_to_ppi_control_information;
pub mod dscp_to_ppi_mapping_information;
pub mod dstt_port_number;
pub mod duplicating_parameters;
pub mod duration_measurement;
pub mod end_time;
pub mod error_indication_report;
pub mod ethernet_context_information;
pub mod ethernet_filter_id;
pub mod ethernet_filter_properties;
pub mod ethernet_inactivity_timer;
pub mod ethernet_packet_filter;
pub mod ethernet_pdu_session_information;
pub mod ethernet_traffic_information;
pub mod ethertype;
pub mod event_notification_uri;
pub mod event_quota;
pub mod event_threshold;
pub mod event_time_stamp;
pub mod extended_dl_buffering_notification_policy;
pub mod f_teid;
pub mod failed_rule_id;
pub mod far_id;
pub mod flow_information;
pub mod forwarding_parameters;
pub mod forwarding_policy;
pub mod fq_csid;
pub mod framed_ipv6_route;
pub mod framed_route;
pub mod framed_routing;
pub mod fseid;
pub mod gate_status;
pub mod gbr;
pub mod graceful_release_period;
pub mod group_id;
pub mod gtpu_path_interface_type;
pub mod gtpu_path_qos_control_information;
pub mod gtpu_path_qos_report;
pub mod header_enrichment;
pub mod hplmn_s_nssai;
pub mod inactivity_detection_time;
pub mod ip_address_and_port_number_replacement;
pub mod ip_multicast_address;
pub mod ip_multicast_addressing_info;
pub mod ip_version;
pub mod join_ip_multicast_information_within_usage_report;
pub mod l2tp_session_indications;
pub mod l2tp_session_information;
pub mod l2tp_tunnel_information;
pub mod l2tp_user_authentication;
pub mod leave_ip_multicast_information_within_usage_report;
pub mod link_specific_multipath_ip_address;
pub mod linked_urr_id;
pub mod lns_address;
pub mod load_control_information;
pub mod local_ingress_tunnel;
pub mod mac_address;
pub mod mac_addresses_detected;
pub mod mac_addresses_removed;
pub mod mapped_n6_ip_address;
pub mod mar_id;
pub mod maximum_packet_delay;
pub mod maximum_receive_unit;
pub mod mbr;
pub mod mbs_multicast_parameters;
pub mod mbs_session_identifier;
pub mod mbs_session_n4_control_information;
pub mod mbs_session_n4_information;
pub mod mbs_session_n4mb_control_information;
pub mod mbs_session_n4mb_information;
pub mod mbs_unicast_parameters_id;
pub mod mbsn4_resp_flags;
pub mod mbsn4mb_req_flags;
pub mod measurement_indication;
pub mod measurement_information;
pub mod measurement_method;
pub mod measurement_period;
pub mod media_transport_protocol;
pub mod metadata;
pub mod metric;
pub mod minimum_packet_delay;
pub mod minimum_wait_time;
pub mod monitoring_time;
pub mod mpquic_address_information;
pub mod mpquic_control_information;
pub mod mpquic_parameters;
pub mod mptcp_address_information;
pub mod mptcp_applicable_indication;
pub mod mptcp_control_information;
pub mod mptcp_parameters;
pub mod mt_sdt_control_information;
pub mod mtedt_control_information;
pub mod multicast_transport_information;
pub mod multiplier;
pub mod n6_jitter_measurement;
pub mod n6_routing_information;
pub mod nbns_server_address;
pub mod network_instance;
pub mod nf_instance_id;
pub mod node_id;
pub mod node_report_type;
pub mod non_tgpp_access_forwarding_action_information;
pub mod notification_correlation_id;
pub mod number_of_reports;
pub mod number_of_ue_ip_addresses;
pub mod nwtt_port_number;
pub mod oci_flags;
pub mod offending_ie;
pub mod offending_ie_information;
pub mod outer_header_creation;
pub mod outer_header_removal;
pub mod overload_control_information;
pub mod packet_delay_thresholds;
pub mod packet_rate;
pub mod packet_rate_status;
pub mod packet_rate_status_report;
pub mod packet_rate_status_report_within_session_modification_response;
pub mod packet_replication_and_detection_carry_on_information;
pub mod paging_policy_indicator;
pub mod partial_failure_information;
pub mod path_failure_report;
pub mod pdi;
pub mod pdn_type;
pub mod pdr_id;
pub mod peer_up_restart_report;
pub mod pfcp_association_release_request;
pub mod pfcp_session_change_info;
pub mod pfcp_session_retention_information;
pub mod pfcpas_req_flags;
pub mod pfcpas_rsp_flags;
pub mod pfcpau_req_flags;
pub mod pfcpsdrsp_flags;
pub mod pfcpse_req_flags;
pub mod pfcpsm_req_flags;
pub mod pfcpsr_req_flags;
pub mod pfcpsrrsp_flags;
pub mod pfd_contents;
pub mod pfd_context;
pub mod pmf_address_information;
pub mod pmf_control_information;
pub mod pmf_parameters;
pub mod port_management_information_container;
pub mod precedence;
pub mod predefined_rules_name;
pub mod priority;
pub mod protocol_description;
pub mod provide_atsss_control_information;
pub mod provide_rds_configuration_information;
pub mod proxying;
pub mod qer_control_indications;
pub mod qer_correlation_id;
pub mod qer_id;
pub mod qer_indications;
pub mod qfi;
pub mod qos_information_in_gtpu_path_qos_report;
pub mod qos_monitoring_measurement;
pub mod qos_monitoring_per_qos_flow_control_information;
pub mod qos_monitoring_report;
pub mod qos_report_trigger;
pub mod query_packet_rate_status_within_session_modification_request;
pub mod query_urr;
pub mod query_urr_reference;
pub mod quota_holding_time;
pub mod quota_validity_time;
pub mod rat_type;
pub mod rds_configuration_information;
pub mod recovery_time_stamp;
pub mod redirect_information;
pub mod redundant_transmission_forwarding_parameters;
pub mod redundant_transmission_parameters;
pub mod remote_gtpu_peer;
pub mod remove_bar;
pub mod remove_far;
pub mod remove_mar;
pub mod remove_mbs_unicast_parameters;
pub mod remove_pdr;
pub mod remove_qer;
pub mod remove_srr;
pub mod remove_traffic_endpoint;
pub mod remove_urr;
pub mod report_type;
pub mod reporting_control_information;
pub mod reporting_flags;
pub mod reporting_frequency;
pub mod reporting_suggestion_info;
pub mod reporting_thresholds;
pub mod reporting_triggers;
pub mod requested_access_availability_information;
pub mod requested_clock_drift_information;
pub mod requested_qos_monitoring;
pub mod rqi;
pub mod rtp_header_extension_additional_information;
pub mod rtp_header_extension_id;
pub mod rtp_header_extension_information;
pub mod rtp_header_extension_type;
pub mod rtp_payload_format;
pub mod rtp_payload_information;
pub mod rtp_payload_type;
pub mod s_tag;
pub mod sdf_filter;
pub mod sequence_number;
pub mod session_report;
pub mod smf_set_id;
pub mod snssai;
pub mod source_interface;
pub mod source_ip_address;
pub mod srr_id;
pub mod start_time;
pub mod steering_functionality;
pub mod steering_mode;
pub mod steering_mode_indicator;
pub mod subsequent_event_quota;
pub mod subsequent_event_threshold;
pub mod subsequent_time_quota;
pub mod subsequent_time_threshold;
pub mod subsequent_volume_quota;
pub mod subsequent_volume_threshold;
pub mod suggested_buffering_packets_count;
pub mod tgpp_access_forwarding_action_information;
pub mod three_gpp_interface_type;
pub mod thresholds;
pub mod time_of_first_packet;
pub mod time_of_last_packet;
pub mod time_offset_measurement;
pub mod time_offset_threshold;
pub mod time_quota;
pub mod time_quota_mechanism;
pub mod time_threshold;
pub mod timer;
pub mod tl_container;
pub mod trace_information;
pub mod traffic_endpoint_id;
pub mod traffic_parameter_measurement_control_information;
pub mod traffic_parameter_measurement_indication;
pub mod traffic_parameter_measurement_report;
pub mod traffic_parameter_threshold;
pub mod transport_delay_reporting;
pub mod transport_level_marking;
pub mod transport_mode;
pub mod tsc_management_information_within_session_modification_request;
pub mod tsc_management_information_within_session_modification_response;
pub mod tsc_management_information_within_session_report_request;
pub mod tsn_bridge_id;
pub mod tsn_time_domain_number;
pub mod tunnel_password;
pub mod tunnel_preference;
pub mod ue_ip_address;
pub mod ue_ip_address_pool_identity;
pub mod ue_ip_address_pool_information;
pub mod ue_ip_address_usage_information;
pub mod ue_level_measurements_configuration;
pub mod ul_periodicity;
pub mod up_function_features;
pub mod update_bar;
pub mod update_bar_within_session_report_response;
pub mod update_duplicating_parameters;
pub mod update_far;
pub mod update_forwarding_parameters;
pub mod update_mar;
pub mod update_non_tgpp_access_forwarding_action_information;
pub mod update_pdr;
pub mod update_qer;
pub mod update_srr;
pub mod update_tgpp_access_forwarding_action_information;
pub mod update_traffic_endpoint;
pub mod update_urr;
pub mod updated_pdr;
pub mod ur_seqn;
pub mod uri;
pub mod urr_id;
pub mod usage_information;
pub mod usage_report;
pub mod usage_report_sdr;
pub mod usage_report_smr;
pub mod usage_report_srr;
pub mod usage_report_trigger;
pub mod user_id;
pub mod user_plane_inactivity_timer;
pub mod user_plane_path_failure_report;
pub mod user_plane_path_recovery_report;
pub mod validity_timer;
pub mod vendor_specific_node_report_type;
pub mod volume_measurement;
pub mod volume_quota;
pub mod weight;
pub mod volume_threshold;
pub use alternative_smf_ip_address::AlternativeSmfIpAddress;
pub use gtpu_path_qos_control_information::GtpuPathQosControlInformation;
pub use nf_instance_id::NfInstanceId;
pub use node_id::NodeId;
pub use pfcp_session_change_info::PfcpSessionChangeInfo;
pub use pfcp_session_retention_information::PfcpSessionRetentionInformation;
pub use pfcpas_req_flags::PfcpasReqFlags;
pub use pfcpas_rsp_flags::PfcpasRspFlags;
pub use query_urr::QueryUrr;
pub use recovery_time_stamp::RecoveryTimeStamp;
pub use smf_set_id::SmfSetId;
pub use traffic_endpoint_id::TrafficEndpointId;
pub use update_duplicating_parameters::UpdateDuplicatingParameters;
pub use user_plane_path_recovery_report::UserPlanePathRecoveryReport;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u16)]
pub enum IeType {
CreatePdr = 1,
Pdi = 2,
CreateFar = 3,
ForwardingParameters = 4,
DuplicatingParameters = 5,
CreateUrr = 6,
CreateQer = 7,
CreatedPdr = 8,
UpdatePdr = 9,
UpdateFar = 10,
UpdateForwardingParameters = 11,
UpdateBarWithinSessionReportResponse = 12,
UpdateUrr = 13,
UpdateQer = 14,
RemovePdr = 15,
RemoveFar = 16,
RemoveUrr = 17,
RemoveQer = 18,
Cause = 19,
SourceInterface = 20,
Fteid = 21,
NetworkInstance = 22,
SdfFilter = 23,
ApplicationId = 24,
GateStatus = 25,
Mbr = 26,
Gbr = 27,
QerCorrelationId = 28,
Precedence = 29,
TransportLevelMarking = 30,
VolumeThreshold = 31,
TimeThreshold = 32,
MonitoringTime = 33,
SubsequentVolumeThreshold = 34,
SubsequentTimeThreshold = 35,
InactivityDetectionTime = 36,
ReportingTriggers = 37,
RedirectInformation = 38,
ReportType = 39,
OffendingIe = 40,
ForwardingPolicy = 41,
DestinationInterface = 42,
UpFunctionFeatures = 43,
ApplyAction = 44,
DownlinkDataServiceInformation = 45,
DownlinkDataNotificationDelay = 46,
DlBufferingDuration = 47,
DlBufferingSuggestedPacketCount = 48,
PfcpsmReqFlags = 49,
PfcpsrrspFlags = 50,
LoadControlInformation = 51,
SequenceNumber = 52,
Metric = 53,
OverloadControlInformation = 54,
Timer = 55,
PdrId = 56,
Fseid = 57,
ApplicationIdsPfds = 58,
PfdContext = 59,
NodeId = 60,
PfdContents = 61,
MeasurementMethod = 62,
UsageReportTrigger = 63,
MeasurementPeriod = 64,
FqCsid = 65,
VolumeMeasurement = 66,
DurationMeasurement = 67,
ApplicationDetectionInformation = 68,
TimeOfFirstPacket = 69,
TimeOfLastPacket = 70,
QuotaHoldingTime = 71,
DroppedDlTrafficThreshold = 72,
VolumeQuota = 73,
TimeQuota = 74,
StartTime = 75,
EndTime = 76,
QueryUrr = 77,
UsageReportWithinSessionModificationResponse = 78,
UsageReportWithinSessionDeletionResponse = 79,
UsageReportWithinSessionReportRequest = 80,
UrrId = 81,
LinkedUrrId = 82,
DownlinkDataReport = 83,
OuterHeaderCreation = 84,
CpFunctionFeatures = 89,
UsageInformation = 90,
ApplicationInstanceId = 91,
FlowInformation = 92,
UeIpAddress = 93,
PacketRate = 94,
OuterHeaderRemoval = 95,
RecoveryTimeStamp = 96,
DlFlowLevelMarking = 97,
HeaderEnrichment = 98,
ErrorIndicationReport = 99,
MeasurementInformation = 100,
NodeReportType = 101,
UserPlanePathFailureReport = 102,
RemoteGtpuPeer = 103,
UrSeqn = 104,
UpdateDuplicatingParameters = 105,
ActivatePredefinedRules = 106,
DeactivatePredefinedRules = 107,
FarId = 108,
QerId = 109,
OciFlags = 110,
PfcpAssociationReleaseRequest = 111,
GracefulReleasePeriod = 112,
PdnType = 113,
FailedRuleId = 114,
TimeQuotaMechanism = 115,
UserPlaneIpResourceInformation = 116,
UserPlaneInactivityTimer = 117,
AggregatedUrrs = 118,
Multiplier = 119,
AggregatedUrrId = 120,
SubsequentVolumeQuota = 121,
SubsequentTimeQuota = 122,
Rqi = 123,
Qfi = 124,
QueryUrrReference = 125,
AdditionalUsageReportsInformation = 126,
CreateTrafficEndpoint = 127,
CreatedTrafficEndpoint = 128,
UpdateTrafficEndpoint = 129,
RemoveTrafficEndpoint = 130,
TrafficEndpointId = 131,
CreateBar = 85,
UpdateBar = 86,
RemoveBar = 87,
BarId = 88,
EthernetPacketFilter = 132,
MacAddress = 133,
CTag = 134,
STag = 135,
Ethertype = 136,
Proxying = 137,
EthernetFilterId = 138,
EthernetFilterProperties = 139,
SuggestedBufferingPacketsCount = 140,
UserId = 141,
EthernetPduSessionInformation = 142,
EthernetTrafficInformation = 143,
MacAddressesDetected = 144,
MacAddressesRemoved = 145,
EthernetInactivityTimer = 146,
AdditionalMonitoringTime = 147,
EventQuota = 148,
EventThreshold = 149,
SubsequentEventQuota = 150,
SubsequentEventThreshold = 151,
TraceInformation = 152,
FramedRoute = 153,
FramedRouting = 154,
FramedIpv6Route = 155,
EventTimeStamp = 156,
AveragingWindow = 157,
PagingPolicyIndicator = 158,
ApnDnn = 159,
TgppInterfaceType = 160,
PfcpsrReqFlags = 161,
PfcpauReqFlags = 162,
ActivationTime = 163,
DeactivationTime = 164,
CreateMar = 165,
TgppAccessForwardingActionInformation = 166,
NonTgppAccessForwardingActionInformation = 167,
RemoveMar = 168,
UpdateMar = 169,
MarId = 170,
SteeringFunctionality = 171,
SteeringMode = 172,
Weight = 173,
Priority = 174,
UpdateTgppAccessForwardingActionInformation = 175,
UpdateNonTgppAccessForwardingActionInformation = 176,
UeIpAddressPoolIdentity = 177,
AlternativeSmfIpAddress = 178,
PacketReplicationAndDetectionCarryOnInformation = 179,
SmfSetId = 180,
QuotaValidityTime = 181,
NumberOfReports = 182,
PfcpSessionRetentionInformation = 183,
PfcpasRspFlags = 184,
CpPfcpEntityIpAddress = 185,
PfcpseReqFlags = 186,
UserPlanePathRecoveryReport = 187,
IpMulticastAddressingInfo = 188,
JoinIpMulticastInformationWithinUsageReport = 189,
LeaveIpMulticastInformationWithinUsageReport = 190,
IpMulticastAddress = 191,
SourceIpAddress = 192,
PacketRateStatus = 193,
CreateBridgeInfoForTsc = 194,
CreatedBridgeInfoForTsc = 195,
DsttPortNumber = 196,
NwttPortNumber = 197,
TsnBridgeId = 198,
TscManagementInformationWithinSessionModificationRequest = 199,
TscManagementInformationWithinSessionModificationResponse = 200,
TscManagementInformationWithinSessionReportRequest = 201,
PortManagementInformationContainer = 202,
ClockDriftControlInformation = 203,
RequestedClockDriftInformation = 204,
ClockDriftReport = 205,
TsnTimeDomainNumber = 206,
TimeOffsetThreshold = 207,
CumulativeRateRatioThreshold = 208,
TimeOffsetMeasurement = 209,
CumulativeRateRatioMeasurement = 210,
RemoveSrr = 211,
CreateSrr = 212,
UpdateSrr = 213,
SessionReport = 214,
SrrId = 215,
AccessAvailabilityControlInformation = 216,
RequestedAccessAvailabilityInformation = 217,
AccessAvailabilityReport = 218,
AccessAvailabilityInformation = 219,
ProvideAtsssControlInformation = 220,
AtsssControlParameters = 221,
MptcpControlInformation = 222,
AtsssLlControlInformation = 223,
PmfControlInformation = 224,
MptcpParameters = 225,
AtsssLlParameters = 226,
PmfParameters = 227,
MptcpAddressInformation = 228,
UeLinkSpecificIpAddress = 229,
PmfAddressInformation = 230,
AtsssLlInformation = 231,
DataNetworkAccessIdentifier = 232,
UeIpAddressPoolInformation = 233,
AveragePacketDelay = 234,
MinimumPacketDelay = 235,
MaximumPacketDelay = 236,
QosReportTrigger = 237,
GtpuPathQosControlInformation = 238,
GtpuPathQosReport = 239,
QosInformationInGtpuPathQosReport = 240,
GtpuPathInterfaceType = 241,
QosMonitoringPerQosFlowControlInformation = 242,
RequestedQosMonitoring = 243,
ReportingFrequency = 244,
PacketDelayThresholds = 245,
MinimumWaitTime = 246,
QosMonitoringReport = 247,
QosMonitoringMeasurement = 248,
MtedtControlInformation = 249,
DlDataPacketsSize = 250,
QerControlIndications = 251,
PacketRateStatusReport = 252,
NfInstanceId = 253,
EthernetContextInformation = 254,
RedundantTransmissionParameters = 255,
UpdatedPdr = 256,
Snssai = 257,
IpVersion = 258,
PfcpasReqFlags = 259,
DataStatus = 260,
ProvideRdsConfigurationInformation = 261,
RdsConfigurationInformation = 262,
QueryPacketRateStatusWithinSessionModificationRequest = 263,
PacketRateStatusReportWithinSessionModificationResponse = 264,
MptcpApplicableIndication = 265,
BridgeManagementInformationContainer = 266,
UeIpAddressUsageInformation = 267,
NumberOfUeIpAddresses = 268,
ValidityTimer = 269,
RedundantTransmissionForwardingParameters = 270,
TransportDelayReporting = 271,
PartialFailureInformation = 272,
OffendingIeInformation = 274,
RatType = 275,
L2tpTunnelInformation = 276,
L2tpSessionInformation = 277,
L2tpUserAuthentication = 278,
CreatedL2tpSession = 279,
LnsAddress = 280,
TunnelPreference = 281,
CallingNumber = 282,
CalledNumber = 283,
L2tpSessionIndications = 284,
DnsServerAddress = 285,
NbnsServerAddress = 286,
MaximumReceiveUnit = 287,
Thresholds = 288,
SteeringModeIndicator = 289,
PfcpSessionChangeInfo = 290,
GroupId = 291,
CpIpAddress = 292,
IpAddressAndPortNumberReplacement = 293,
DnsQueryResponseFilter = 294,
DirectReportingInformation = 295,
EventNotificationUri = 296,
NotificationCorrelationId = 297,
ReportingFlags = 298,
PredefinedRulesName = 299,
MbsSessionN4mbControlInformation = 300,
MbsMulticastParameters = 301,
AddMbsUnicastParameters = 302,
MbsSessionN4mbInformation = 303,
RemoveMbsUnicastParameters = 304,
MbsSessionIdentifier = 305,
MulticastTransportInformation = 306,
Mbsn4mbReqFlags = 307,
LocalIngressTunnel = 308,
MbsUnicastParametersId = 309,
MbsSessionN4ControlInformation = 310,
MbsSessionN4Information = 311,
Mbsn4RespFlags = 312,
TunnelPassword = 313,
AreaSessionId = 314,
PeerUpRestartReport = 315,
DscpToPpiControlInformation = 316,
DscpToPpiMappingInformation = 317,
PfcpsdrspFlags = 318,
QerIndications = 319,
VendorSpecificNodeReportType = 320,
ConfiguredTimeDomain = 321,
Metadata = 322,
TrafficParameterMeasurementControlInformation = 323,
TrafficParameterMeasurementReport = 324,
TrafficParameterThreshold = 325,
DlPeriodicity = 326,
N6JitterMeasurement = 327,
TrafficParameterMeasurementIndication = 328,
UlPeriodicity = 329,
MpquicControlInformation = 330,
MpquicParameters = 331,
MpquicAddressInformation = 332,
TransportMode = 333,
ProtocolDescription = 334,
ReportingSuggestionInfo = 335,
TlContainer = 336,
MeasurementIndication = 337,
HplmnSNssai = 338,
MediaTransportProtocol = 339,
RtpHeaderExtensionInformation = 340,
RtpPayloadInformation = 341,
RtpHeaderExtensionType = 342,
RtpHeaderExtensionId = 343,
RtpPayloadType = 344,
RtpPayloadFormat = 345,
ExtendedDlBufferingNotificationPolicy = 346,
MtSdtControlInformation = 347,
ReportingThresholds = 348,
RtpHeaderExtensionAdditionalInformation = 349,
MappedN6IpAddress = 350,
N6RoutingInformation = 351,
Uri = 352,
UeLevelMeasurementsConfiguration = 353,
ReportingControlInformation = 389,
Unknown = 0,
}
impl From<u16> for IeType {
fn from(v: u16) -> Self {
match v {
1 => IeType::CreatePdr,
2 => IeType::Pdi,
3 => IeType::CreateFar,
4 => IeType::ForwardingParameters,
5 => IeType::DuplicatingParameters,
6 => IeType::CreateUrr,
7 => IeType::CreateQer,
8 => IeType::CreatedPdr,
9 => IeType::UpdatePdr,
10 => IeType::UpdateFar,
11 => IeType::UpdateForwardingParameters,
12 => IeType::UpdateBarWithinSessionReportResponse,
13 => IeType::UpdateUrr,
14 => IeType::UpdateQer,
15 => IeType::RemovePdr,
16 => IeType::RemoveFar,
17 => IeType::RemoveUrr,
18 => IeType::RemoveQer,
19 => IeType::Cause,
20 => IeType::SourceInterface,
21 => IeType::Fteid,
22 => IeType::NetworkInstance,
23 => IeType::SdfFilter,
24 => IeType::ApplicationId,
25 => IeType::GateStatus,
26 => IeType::Mbr,
27 => IeType::Gbr,
28 => IeType::QerCorrelationId,
29 => IeType::Precedence,
30 => IeType::TransportLevelMarking,
31 => IeType::VolumeThreshold,
32 => IeType::TimeThreshold,
33 => IeType::MonitoringTime,
34 => IeType::SubsequentVolumeThreshold,
35 => IeType::SubsequentTimeThreshold,
36 => IeType::InactivityDetectionTime,
37 => IeType::ReportingTriggers,
38 => IeType::RedirectInformation,
39 => IeType::ReportType,
40 => IeType::OffendingIe,
41 => IeType::ForwardingPolicy,
42 => IeType::DestinationInterface,
43 => IeType::UpFunctionFeatures,
44 => IeType::ApplyAction,
45 => IeType::DownlinkDataServiceInformation,
46 => IeType::DownlinkDataNotificationDelay,
47 => IeType::DlBufferingDuration,
48 => IeType::DlBufferingSuggestedPacketCount,
49 => IeType::PfcpsmReqFlags,
50 => IeType::PfcpsrrspFlags,
51 => IeType::LoadControlInformation,
52 => IeType::SequenceNumber,
53 => IeType::Metric,
54 => IeType::OverloadControlInformation,
55 => IeType::Timer,
56 => IeType::PdrId,
57 => IeType::Fseid,
58 => IeType::ApplicationIdsPfds,
59 => IeType::PfdContext,
60 => IeType::NodeId,
61 => IeType::PfdContents,
62 => IeType::MeasurementMethod,
63 => IeType::UsageReportTrigger,
64 => IeType::MeasurementPeriod,
65 => IeType::FqCsid,
66 => IeType::VolumeMeasurement,
67 => IeType::DurationMeasurement,
68 => IeType::ApplicationDetectionInformation,
69 => IeType::TimeOfFirstPacket,
70 => IeType::TimeOfLastPacket,
71 => IeType::QuotaHoldingTime,
72 => IeType::DroppedDlTrafficThreshold,
73 => IeType::VolumeQuota,
74 => IeType::TimeQuota,
75 => IeType::StartTime,
76 => IeType::EndTime,
77 => IeType::QueryUrr,
78 => IeType::UsageReportWithinSessionModificationResponse,
79 => IeType::UsageReportWithinSessionDeletionResponse,
80 => IeType::UsageReportWithinSessionReportRequest,
81 => IeType::UrrId,
82 => IeType::LinkedUrrId,
83 => IeType::DownlinkDataReport,
84 => IeType::OuterHeaderCreation,
93 => IeType::UeIpAddress,
95 => IeType::OuterHeaderRemoval,
96 => IeType::RecoveryTimeStamp,
106 => IeType::ActivatePredefinedRules,
107 => IeType::DeactivatePredefinedRules,
85 => IeType::CreateBar,
86 => IeType::UpdateBar,
87 => IeType::RemoveBar,
88 => IeType::BarId,
89 => IeType::CpFunctionFeatures,
90 => IeType::UsageInformation,
91 => IeType::ApplicationInstanceId,
92 => IeType::FlowInformation,
94 => IeType::PacketRate,
97 => IeType::DlFlowLevelMarking,
98 => IeType::HeaderEnrichment,
99 => IeType::ErrorIndicationReport,
100 => IeType::MeasurementInformation,
101 => IeType::NodeReportType,
102 => IeType::UserPlanePathFailureReport,
103 => IeType::RemoteGtpuPeer,
104 => IeType::UrSeqn,
105 => IeType::UpdateDuplicatingParameters,
108 => IeType::FarId,
109 => IeType::QerId,
110 => IeType::OciFlags,
111 => IeType::PfcpAssociationReleaseRequest,
112 => IeType::GracefulReleasePeriod,
113 => IeType::PdnType,
114 => IeType::FailedRuleId,
115 => IeType::TimeQuotaMechanism,
116 => IeType::UserPlaneIpResourceInformation,
117 => IeType::UserPlaneInactivityTimer,
118 => IeType::AggregatedUrrs,
119 => IeType::Multiplier,
120 => IeType::AggregatedUrrId,
121 => IeType::SubsequentVolumeQuota,
122 => IeType::SubsequentTimeQuota,
123 => IeType::Rqi,
124 => IeType::Qfi,
125 => IeType::QueryUrrReference,
126 => IeType::AdditionalUsageReportsInformation,
127 => IeType::CreateTrafficEndpoint,
128 => IeType::CreatedTrafficEndpoint,
129 => IeType::UpdateTrafficEndpoint,
130 => IeType::RemoveTrafficEndpoint,
131 => IeType::TrafficEndpointId,
132 => IeType::EthernetPacketFilter,
133 => IeType::MacAddress,
134 => IeType::CTag,
135 => IeType::STag,
136 => IeType::Ethertype,
137 => IeType::Proxying,
138 => IeType::EthernetFilterId,
139 => IeType::EthernetFilterProperties,
140 => IeType::SuggestedBufferingPacketsCount,
141 => IeType::UserId,
142 => IeType::EthernetPduSessionInformation,
143 => IeType::EthernetTrafficInformation,
144 => IeType::MacAddressesDetected,
145 => IeType::MacAddressesRemoved,
146 => IeType::EthernetInactivityTimer,
147 => IeType::AdditionalMonitoringTime,
148 => IeType::EventQuota,
149 => IeType::EventThreshold,
150 => IeType::SubsequentEventQuota,
151 => IeType::SubsequentEventThreshold,
152 => IeType::TraceInformation,
153 => IeType::FramedRoute,
154 => IeType::FramedRouting,
155 => IeType::FramedIpv6Route,
156 => IeType::EventTimeStamp,
157 => IeType::AveragingWindow,
158 => IeType::PagingPolicyIndicator,
159 => IeType::ApnDnn,
160 => IeType::TgppInterfaceType,
161 => IeType::PfcpsrReqFlags,
162 => IeType::PfcpauReqFlags,
163 => IeType::ActivationTime,
164 => IeType::DeactivationTime,
165 => IeType::CreateMar,
166 => IeType::TgppAccessForwardingActionInformation,
167 => IeType::NonTgppAccessForwardingActionInformation,
168 => IeType::RemoveMar,
169 => IeType::UpdateMar,
170 => IeType::MarId,
171 => IeType::SteeringFunctionality,
172 => IeType::SteeringMode,
173 => IeType::Weight,
174 => IeType::Priority,
175 => IeType::UpdateTgppAccessForwardingActionInformation,
176 => IeType::UpdateNonTgppAccessForwardingActionInformation,
177 => IeType::UeIpAddressPoolIdentity,
178 => IeType::AlternativeSmfIpAddress,
179 => IeType::PacketReplicationAndDetectionCarryOnInformation,
180 => IeType::SmfSetId,
181 => IeType::QuotaValidityTime,
182 => IeType::NumberOfReports,
183 => IeType::PfcpSessionRetentionInformation,
184 => IeType::PfcpasRspFlags,
185 => IeType::CpPfcpEntityIpAddress,
186 => IeType::PfcpseReqFlags,
187 => IeType::UserPlanePathRecoveryReport,
188 => IeType::IpMulticastAddressingInfo,
189 => IeType::JoinIpMulticastInformationWithinUsageReport,
190 => IeType::LeaveIpMulticastInformationWithinUsageReport,
191 => IeType::IpMulticastAddress,
192 => IeType::SourceIpAddress,
193 => IeType::PacketRateStatus,
194 => IeType::CreateBridgeInfoForTsc,
195 => IeType::CreatedBridgeInfoForTsc,
196 => IeType::DsttPortNumber,
197 => IeType::NwttPortNumber,
198 => IeType::TsnBridgeId,
199 => IeType::TscManagementInformationWithinSessionModificationRequest,
200 => IeType::TscManagementInformationWithinSessionModificationResponse,
201 => IeType::TscManagementInformationWithinSessionReportRequest,
202 => IeType::PortManagementInformationContainer,
203 => IeType::ClockDriftControlInformation,
204 => IeType::RequestedClockDriftInformation,
205 => IeType::ClockDriftReport,
206 => IeType::TsnTimeDomainNumber,
207 => IeType::TimeOffsetThreshold,
208 => IeType::CumulativeRateRatioThreshold,
209 => IeType::TimeOffsetMeasurement,
210 => IeType::CumulativeRateRatioMeasurement,
211 => IeType::RemoveSrr,
212 => IeType::CreateSrr,
213 => IeType::UpdateSrr,
214 => IeType::SessionReport,
215 => IeType::SrrId,
216 => IeType::AccessAvailabilityControlInformation,
217 => IeType::RequestedAccessAvailabilityInformation,
218 => IeType::AccessAvailabilityReport,
219 => IeType::AccessAvailabilityInformation,
220 => IeType::ProvideAtsssControlInformation,
221 => IeType::AtsssControlParameters,
222 => IeType::MptcpControlInformation,
223 => IeType::AtsssLlControlInformation,
224 => IeType::PmfControlInformation,
225 => IeType::MptcpParameters,
226 => IeType::AtsssLlParameters,
227 => IeType::PmfParameters,
228 => IeType::MptcpAddressInformation,
229 => IeType::UeLinkSpecificIpAddress,
230 => IeType::PmfAddressInformation,
231 => IeType::AtsssLlInformation,
232 => IeType::DataNetworkAccessIdentifier,
233 => IeType::UeIpAddressPoolInformation,
234 => IeType::AveragePacketDelay,
235 => IeType::MinimumPacketDelay,
236 => IeType::MaximumPacketDelay,
237 => IeType::QosReportTrigger,
238 => IeType::GtpuPathQosControlInformation,
239 => IeType::GtpuPathQosReport,
240 => IeType::QosInformationInGtpuPathQosReport,
241 => IeType::GtpuPathInterfaceType,
242 => IeType::QosMonitoringPerQosFlowControlInformation,
243 => IeType::RequestedQosMonitoring,
244 => IeType::ReportingFrequency,
245 => IeType::PacketDelayThresholds,
246 => IeType::MinimumWaitTime,
247 => IeType::QosMonitoringReport,
248 => IeType::QosMonitoringMeasurement,
249 => IeType::MtedtControlInformation,
250 => IeType::DlDataPacketsSize,
251 => IeType::QerControlIndications,
252 => IeType::PacketRateStatusReport,
253 => IeType::NfInstanceId,
254 => IeType::EthernetContextInformation,
255 => IeType::RedundantTransmissionParameters,
256 => IeType::UpdatedPdr,
257 => IeType::Snssai,
258 => IeType::IpVersion,
259 => IeType::PfcpasReqFlags,
260 => IeType::DataStatus,
261 => IeType::ProvideRdsConfigurationInformation,
262 => IeType::RdsConfigurationInformation,
263 => IeType::QueryPacketRateStatusWithinSessionModificationRequest,
264 => IeType::PacketRateStatusReportWithinSessionModificationResponse,
265 => IeType::MptcpApplicableIndication,
266 => IeType::BridgeManagementInformationContainer,
267 => IeType::UeIpAddressUsageInformation,
268 => IeType::NumberOfUeIpAddresses,
269 => IeType::ValidityTimer,
270 => IeType::RedundantTransmissionForwardingParameters,
271 => IeType::TransportDelayReporting,
272 => IeType::PartialFailureInformation,
274 => IeType::OffendingIeInformation,
275 => IeType::RatType,
276 => IeType::L2tpTunnelInformation,
277 => IeType::L2tpSessionInformation,
278 => IeType::L2tpUserAuthentication,
279 => IeType::CreatedL2tpSession,
280 => IeType::LnsAddress,
281 => IeType::TunnelPreference,
282 => IeType::CallingNumber,
283 => IeType::CalledNumber,
284 => IeType::L2tpSessionIndications,
285 => IeType::DnsServerAddress,
286 => IeType::NbnsServerAddress,
287 => IeType::MaximumReceiveUnit,
288 => IeType::Thresholds,
289 => IeType::SteeringModeIndicator,
290 => IeType::PfcpSessionChangeInfo,
291 => IeType::GroupId,
292 => IeType::CpIpAddress,
293 => IeType::IpAddressAndPortNumberReplacement,
294 => IeType::DnsQueryResponseFilter,
295 => IeType::DirectReportingInformation,
296 => IeType::EventNotificationUri,
297 => IeType::NotificationCorrelationId,
298 => IeType::ReportingFlags,
299 => IeType::PredefinedRulesName,
300 => IeType::MbsSessionN4mbControlInformation,
301 => IeType::MbsMulticastParameters,
302 => IeType::AddMbsUnicastParameters,
303 => IeType::MbsSessionN4mbInformation,
304 => IeType::RemoveMbsUnicastParameters,
305 => IeType::MbsSessionIdentifier,
306 => IeType::MulticastTransportInformation,
307 => IeType::Mbsn4mbReqFlags,
308 => IeType::LocalIngressTunnel,
309 => IeType::MbsUnicastParametersId,
310 => IeType::MbsSessionN4ControlInformation,
311 => IeType::MbsSessionN4Information,
312 => IeType::Mbsn4RespFlags,
313 => IeType::TunnelPassword,
314 => IeType::AreaSessionId,
315 => IeType::PeerUpRestartReport,
316 => IeType::DscpToPpiControlInformation,
317 => IeType::DscpToPpiMappingInformation,
318 => IeType::PfcpsdrspFlags,
319 => IeType::QerIndications,
320 => IeType::VendorSpecificNodeReportType,
321 => IeType::ConfiguredTimeDomain,
322 => IeType::Metadata,
323 => IeType::TrafficParameterMeasurementControlInformation,
324 => IeType::TrafficParameterMeasurementReport,
325 => IeType::TrafficParameterThreshold,
326 => IeType::DlPeriodicity,
327 => IeType::N6JitterMeasurement,
328 => IeType::TrafficParameterMeasurementIndication,
329 => IeType::UlPeriodicity,
330 => IeType::MpquicControlInformation,
331 => IeType::MpquicParameters,
332 => IeType::MpquicAddressInformation,
333 => IeType::TransportMode,
334 => IeType::ProtocolDescription,
335 => IeType::ReportingSuggestionInfo,
336 => IeType::TlContainer,
337 => IeType::MeasurementIndication,
338 => IeType::HplmnSNssai,
339 => IeType::MediaTransportProtocol,
340 => IeType::RtpHeaderExtensionInformation,
341 => IeType::RtpPayloadInformation,
342 => IeType::RtpHeaderExtensionType,
343 => IeType::RtpHeaderExtensionId,
344 => IeType::RtpPayloadType,
345 => IeType::RtpPayloadFormat,
346 => IeType::ExtendedDlBufferingNotificationPolicy,
347 => IeType::MtSdtControlInformation,
348 => IeType::ReportingThresholds,
349 => IeType::RtpHeaderExtensionAdditionalInformation,
350 => IeType::MappedN6IpAddress,
351 => IeType::N6RoutingInformation,
352 => IeType::Uri,
353 => IeType::UeLevelMeasurementsConfiguration,
389 => IeType::ReportingControlInformation,
_ => IeType::Unknown,
}
}
}
pub trait ParseIe: Sized {
fn parse_from_payload(data: &[u8]) -> Result<Self, PfcpError>;
}
pub trait IntoIePayload {
fn into_payload(self) -> Vec<u8>;
}
impl IntoIePayload for Vec<u8> {
fn into_payload(self) -> Vec<u8> {
self
}
}
impl<const N: usize> IntoIePayload for [u8; N] {
fn into_payload(self) -> Vec<u8> {
self.to_vec()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Ie {
pub ie_type: IeType,
pub enterprise_id: Option<u16>,
pub payload: Vec<u8>,
child_ies: Vec<Ie>,
}
impl Ie {
pub fn new(ie_type: IeType, payload: Vec<u8>) -> Self {
Ie {
ie_type,
enterprise_id: None,
payload,
child_ies: Vec::new(),
}
}
pub fn new_vendor_specific(ie_type: IeType, enterprise_id: u16, payload: Vec<u8>) -> Self {
Ie {
ie_type,
enterprise_id: Some(enterprise_id),
payload,
child_ies: Vec::new(),
}
}
pub fn new_grouped(ie_type: IeType, ies: Vec<Ie>) -> Self {
let mut payload = Vec::new();
for ie in &ies {
payload.extend_from_slice(&ie.marshal());
}
Ie {
ie_type,
enterprise_id: None,
payload,
child_ies: ies,
}
}
pub fn from_marshal<T: IntoIePayload>(ie_type: IeType, payload: T) -> Self {
Ie::new(ie_type, payload.into_payload())
}
pub fn len(&self) -> u16 {
let mut length = 4; if self.is_vendor_specific() {
length += 2;
}
length += self.payload.len() as u16;
length
}
pub fn is_empty(&self) -> bool {
self.payload.is_empty()
}
pub fn is_vendor_specific(&self) -> bool {
self.enterprise_id.is_some() || (self.ie_type as u16) & 0x8000 != 0
}
pub fn marshal(&self) -> Vec<u8> {
let mut data = Vec::new();
self.marshal_into(&mut data);
data
}
pub fn marshal_into(&self, buf: &mut Vec<u8>) {
buf.extend_from_slice(&(self.ie_type as u16).to_be_bytes());
let length = if self.is_vendor_specific() {
self.payload.len() as u16 + 2
} else {
self.payload.len() as u16
};
buf.extend_from_slice(&length.to_be_bytes());
if let Some(eid) = self.enterprise_id {
buf.extend_from_slice(&eid.to_be_bytes());
}
buf.extend_from_slice(&self.payload);
}
fn allows_zero_length(ie_type: IeType) -> bool {
matches!(
ie_type,
IeType::NetworkInstance | IeType::ApnDnn | IeType::ForwardingPolicy )
}
pub fn unmarshal(b: &[u8]) -> Result<Self, PfcpError> {
if b.len() < 4 {
return Err(PfcpError::invalid_length("IE", IeType::Unknown, 4, b.len()));
}
let raw_type = u16::from_be_bytes([b[0], b[1]]);
let ie_type = IeType::from(raw_type);
let length = u16::from_be_bytes([b[2], b[3]]);
if length == 0 && !Self::allows_zero_length(ie_type) {
return Err(PfcpError::invalid_value(
"IE",
format!("{:?} (type {})", ie_type, raw_type),
"Zero-length IE not allowed",
));
}
let mut offset = 4;
let enterprise_id = if raw_type & 0x8000 != 0 {
if b.len() < 6 {
return Err(PfcpError::invalid_length(
"Vendor-specific IE",
ie_type,
6,
b.len(),
));
}
offset += 2;
Some(u16::from_be_bytes([b[4], b[5]]))
} else {
None
};
let payload_length = if enterprise_id.is_some() && length >= 2 {
length - 2
} else if enterprise_id.is_some() {
0 } else {
length
};
let end = offset + payload_length as usize;
if b.len() < end {
return Err(PfcpError::invalid_length(
"IE payload",
ie_type,
end,
b.len(),
));
}
let payload = b[offset..end].to_vec();
Ok(Ie {
ie_type,
enterprise_id,
payload,
child_ies: Vec::new(), })
}
pub fn as_u8(&self) -> Result<u8, PfcpError> {
if self.payload.is_empty() {
return Err(PfcpError::invalid_length("IE payload", self.ie_type, 1, 0));
}
Ok(self.payload[0])
}
pub fn as_u16(&self) -> Result<u16, PfcpError> {
if self.payload.len() < 2 {
return Err(PfcpError::invalid_length(
"IE payload",
self.ie_type,
2,
self.payload.len(),
));
}
Ok(u16::from_be_bytes([self.payload[0], self.payload[1]]))
}
pub fn as_u32(&self) -> Result<u32, PfcpError> {
if self.payload.len() < 4 {
return Err(PfcpError::invalid_length(
"IE payload",
self.ie_type,
4,
self.payload.len(),
));
}
Ok(u32::from_be_bytes([
self.payload[0],
self.payload[1],
self.payload[2],
self.payload[3],
]))
}
pub fn as_u64(&self) -> Result<u64, PfcpError> {
if self.payload.len() < 8 {
return Err(PfcpError::invalid_length(
"IE payload",
self.ie_type,
8,
self.payload.len(),
));
}
Ok(u64::from_be_bytes([
self.payload[0],
self.payload[1],
self.payload[2],
self.payload[3],
self.payload[4],
self.payload[5],
self.payload[6],
self.payload[7],
]))
}
pub fn as_string(&self) -> Result<String, PfcpError> {
std::str::from_utf8(&self.payload)
.map(|s| s.to_string())
.map_err(|e| {
PfcpError::invalid_value(
"IE payload",
format!("{:?}", self.ie_type),
format!("Invalid UTF-8: {}", e),
)
})
}
pub fn as_ies(&mut self) -> Result<&[Ie], PfcpError> {
if !self.child_ies.is_empty() {
return Ok(&self.child_ies);
}
let mut offset = 0;
while offset < self.payload.len() {
let ie = Ie::unmarshal(&self.payload[offset..])?;
let ie_len = ie.len() as usize;
self.child_ies.push(ie);
offset += ie_len;
}
Ok(&self.child_ies)
}
pub fn parse<T: ParseIe>(&self) -> Result<T, PfcpError> {
T::parse_from_payload(&self.payload)
}
}
pub fn marshal_ies(ies: &[Ie]) -> Vec<u8> {
let capacity: usize = ies.iter().map(|ie| ie.len() as usize).sum();
let mut data = Vec::with_capacity(capacity);
for ie in ies {
data.extend_from_slice(&ie.marshal());
}
data
}
pub struct IeIterator<'a> {
payload: &'a [u8],
offset: usize,
}
impl<'a> IeIterator<'a> {
pub fn new(payload: &'a [u8]) -> Self {
IeIterator { payload, offset: 0 }
}
}
impl<'a> Iterator for IeIterator<'a> {
type Item = Result<Ie, PfcpError>;
fn next(&mut self) -> Option<Self::Item> {
if self.offset >= self.payload.len() {
return None;
}
match Ie::unmarshal(&self.payload[self.offset..]) {
Ok(ie) => {
let ie_len = ie.len() as usize;
self.offset += ie_len;
Some(Ok(ie))
}
Err(e) => {
self.offset = self.payload.len();
Some(Err(e))
}
}
}
}
pub mod builder_support {
use super::*;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::time::SystemTime;
pub trait IntoIe {
fn into_ie(self) -> Ie;
}
impl IntoIe for SystemTime {
fn into_ie(self) -> Ie {
use crate::ie::recovery_time_stamp::RecoveryTimeStamp;
let ts = RecoveryTimeStamp::new(self);
Ie::new(IeType::RecoveryTimeStamp, ts.marshal().to_vec())
}
}
impl IntoIe for Ipv4Addr {
fn into_ie(self) -> Ie {
use crate::ie::source_ip_address::SourceIpAddress;
let ip = SourceIpAddress::new(Some(self), None);
ip.to_ie()
}
}
impl IntoIe for Ipv6Addr {
fn into_ie(self) -> Ie {
use crate::ie::source_ip_address::SourceIpAddress;
let ip = SourceIpAddress::new(None, Some(self));
ip.to_ie()
}
}
impl IntoIe for IpAddr {
fn into_ie(self) -> Ie {
match self {
IpAddr::V4(addr) => addr.into_ie(),
IpAddr::V6(addr) => addr.into_ie(),
}
}
}
impl IntoIe for &str {
fn into_ie(self) -> Ie {
use crate::ie::node_id::NodeId;
let node_id = NodeId::new_fqdn(self);
node_id.to_ie()
}
}
impl IntoIe for String {
fn into_ie(self) -> Ie {
self.as_str().into_ie()
}
}
impl IntoIe for (u64, Ipv4Addr) {
fn into_ie(self) -> Ie {
use crate::ie::fseid::Fseid;
let (seid, ip) = self;
let fseid = Fseid::new(seid, Some(ip), None);
Ie::new(IeType::Fseid, fseid.marshal())
}
}
impl IntoIe for (u64, Ipv6Addr) {
fn into_ie(self) -> Ie {
use crate::ie::fseid::Fseid;
let (seid, ip) = self;
let fseid = Fseid::new(seid, None, Some(ip));
Ie::new(IeType::Fseid, fseid.marshal())
}
}
impl IntoIe for (u64, IpAddr) {
fn into_ie(self) -> Ie {
let (seid, ip) = self;
match ip {
IpAddr::V4(v4) => (seid, v4).into_ie(),
IpAddr::V6(v6) => (seid, v6).into_ie(),
}
}
}
impl IntoIe for (u32, Ipv4Addr) {
fn into_ie(self) -> Ie {
use crate::ie::f_teid::Fteid;
let (teid, ip) = self;
let fteid = Fteid::new(true, false, teid, Some(ip), None, 0);
Ie::new(IeType::Fteid, fteid.marshal())
}
}
impl IntoIe for (u32, Ipv6Addr) {
fn into_ie(self) -> Ie {
use crate::ie::f_teid::Fteid;
let (teid, ip) = self;
let fteid = Fteid::new(false, true, teid, None, Some(ip), 0);
Ie::new(IeType::Fteid, fteid.marshal())
}
}
impl IntoIe for (u32, IpAddr) {
fn into_ie(self) -> Ie {
let (teid, ip) = self;
match ip {
IpAddr::V4(v4) => (teid, v4).into_ie(),
IpAddr::V6(v6) => (teid, v6).into_ie(),
}
}
}
impl IntoIe for (Ipv4Addr, Ipv6Addr) {
fn into_ie(self) -> Ie {
use crate::ie::ue_ip_address::UeIpAddress;
let (ipv4, ipv6) = self;
let ue_ip = UeIpAddress::new(Some(ipv4), Some(ipv6));
Ie::new(IeType::UeIpAddress, ue_ip.marshal())
}
}
}
pub use builder_support::IntoIe;
macro_rules! impl_parse_ie {
($($ty:ty),* $(,)?) => {
$(
impl ParseIe for $ty {
fn parse_from_payload(data: &[u8]) -> Result<Self, PfcpError> {
Self::unmarshal(data)
}
}
)*
};
}
impl_parse_ie!(
cause::Cause,
node_id::NodeId,
fseid::Fseid,
f_teid::Fteid,
pdr_id::PdrId,
far_id::FarId,
urr_id::UrrId,
qer_id::QerId,
bar_id::BarId,
precedence::Precedence,
source_interface::SourceInterface,
destination_interface::DestinationInterface,
network_instance::NetworkInstance,
apply_action::ApplyAction,
gate_status::GateStatus,
mbr::Mbr,
gbr::Gbr,
reporting_triggers::ReportingTriggers,
report_type::ReportType,
ue_ip_address::UeIpAddress,
outer_header_removal::OuterHeaderRemoval,
outer_header_creation::OuterHeaderCreation,
up_function_features::UPFunctionFeatures,
cp_function_features::CPFunctionFeatures,
recovery_time_stamp::RecoveryTimeStamp,
nf_instance_id::NfInstanceId,
alternative_smf_ip_address::AlternativeSmfIpAddress,
smf_set_id::SmfSetId,
pfcpas_req_flags::PfcpasReqFlags,
pfcpas_rsp_flags::PfcpasRspFlags,
clock_drift_control_information::ClockDriftControlInformation,
clock_drift_report::ClockDriftReport,
gtpu_path_qos_report::GtpuPathQosReport,
qos_information_in_gtpu_path_qos_report::QosInformationInGtpuPathQosReport,
provide_rds_configuration_information::ProvideRdsConfigurationInformation,
rds_configuration_information::RdsConfigurationInformation,
create_pdr::CreatePdr,
create_far::CreateFar,
create_mar::CreateMar,
create_srr::CreateSrr,
update_mar::UpdateMar,
update_srr::UpdateSrr,
tgpp_access_forwarding_action_information::TgppAccessForwardingActionInformation,
non_tgpp_access_forwarding_action_information::NonTgppAccessForwardingActionInformation,
update_tgpp_access_forwarding_action_information::UpdateTgppAccessForwardingActionInformation,
update_non_tgpp_access_forwarding_action_information::UpdateNonTgppAccessForwardingActionInformation,
tsc_management_information_within_session_modification_request::TscManagementInformationWithinSessionModificationRequest,
tsc_management_information_within_session_modification_response::TscManagementInformationWithinSessionModificationResponse,
query_packet_rate_status_within_session_modification_request::QueryPacketRateStatusWithinSessionModificationRequest,
packet_rate_status_report_within_session_modification_response::PacketRateStatusReportWithinSessionModificationResponse,
create_urr::CreateUrr,
create_qer::CreateQer,
create_bar::CreateBar,
created_pdr::CreatedPdr,
pdi::Pdi,
forwarding_parameters::ForwardingParameters,
update_far::UpdateFar,
update_pdr::UpdatePdr,
update_qer::UpdateQer,
update_urr::UpdateUrr,
usage_report_srr::UsageReportSrr,
usage_report_smr::UsageReportSmr,
usage_report_sdr::UsageReportSdr,
pdn_type::PdnType,
provide_atsss_control_information::ProvideAtsssControlInformation,
atsss_control_parameters::AtsssControlParameters,
mptcp_parameters::MptcpParameters,
atsss_ll_parameters::AtsssLlParameters,
pmf_parameters::PmfParameters,
mpquic_parameters::MpquicParameters,
mptcp_control_information::MptcpControlInformation,
atsss_ll_control_information::AtsssLlControlInformation,
pmf_control_information::PmfControlInformation,
mpquic_control_information::MpquicControlInformation,
atsss_ll_information::AtsssLlInformation,
mptcp_address_information::MptcpAddressInformation,
link_specific_multipath_ip_address::LinkSpecificMultipathIpAddress,
pmf_address_information::PmfAddressInformation,
mpquic_address_information::MpquicAddressInformation,
mbs_session_n4mb_control_information::MbsSessionN4mbControlInformation,
mbs_session_n4mb_information::MbsSessionN4mbInformation,
mbs_session_n4_control_information::MbsSessionN4ControlInformation,
mbs_session_n4_information::MbsSessionN4Information,
mbs_multicast_parameters::MbsMulticastParameters,
add_mbs_unicast_parameters::AddMbsUnicastParameters,
remove_mbs_unicast_parameters::RemoveMbsUnicastParameters,
l2tp_tunnel_information::L2tpTunnelInformation,
l2tp_session_information::L2tpSessionInformation,
created_l2tp_session::CreatedL2tpSession,
lns_address::LnsAddress,
tunnel_preference::TunnelPreference,
calling_number::CallingNumber,
called_number::CalledNumber,
l2tp_session_indications::L2tpSessionIndications,
dns_server_address::DnsServerAddress,
nbns_server_address::NbnsServerAddress,
maximum_receive_unit::MaximumReceiveUnit,
aggregated_urr_id::AggregatedUrrId,
bridge_management_information_container::BridgeManagementInformationContainer,
configured_time_domain::ConfiguredTimeDomain,
cumulative_rate_ratio_measurement::CumulativeRateRatioMeasurement,
cumulative_rate_ratio_threshold::CumulativeRateRatioThreshold,
dl_buffering_suggested_packet_count::DlBufferingSuggestedPacketCount,
extended_dl_buffering_notification_policy::ExtendedDlBufferingNotificationPolicy,
gtpu_path_interface_type::GtpuPathInterfaceType,
mbs_unicast_parameters_id::MbsUnicastParametersId,
media_transport_protocol::MediaTransportProtocol,
metadata::Metadata,
minimum_wait_time::MinimumWaitTime,
mt_sdt_control_information::MtSdtControlInformation,
port_management_information_container::PortManagementInformationContainer,
reporting_control_information::ReportingControlInformation,
rtp_header_extension_id::RtpHeaderExtensionId,
rtp_header_extension_type::RtpHeaderExtensionType,
rtp_payload_format::RtpPayloadFormat,
rtp_payload_type::RtpPayloadType,
time_offset_measurement::TimeOffsetMeasurement,
time_offset_threshold::TimeOffsetThreshold,
tl_container::TlContainer,
transport_mode::TransportMode,
ue_level_measurements_configuration::UeLevelMeasurementsConfiguration,
vendor_specific_node_report_type::VendorSpecificNodeReportType,
access_availability_information::AccessAvailabilityInformation,
dscp_to_ppi_mapping_information::DscpToPpiMappingInformation,
local_ingress_tunnel::LocalIngressTunnel,
n6_routing_information::N6RoutingInformation,
packet_delay_thresholds::PacketDelayThresholds,
qos_monitoring_measurement::QosMonitoringMeasurement,
remote_gtpu_peer::RemoteGtpuPeer,
reporting_suggestion_info::ReportingSuggestionInfo,
reporting_thresholds::ReportingThresholds,
traffic_parameter_threshold::TrafficParameterThreshold,
access_availability_control_information::AccessAvailabilityControlInformation,
access_availability_report::AccessAvailabilityReport,
additional_monitoring_time::AdditionalMonitoringTime,
aggregated_urrs::AggregatedUrrs,
create_bridge_info_for_tsc::CreateBridgeInfoForTsc,
created_bridge_info_for_tsc::CreatedBridgeInfoForTsc,
downlink_data_report::DownlinkDataReport,
dscp_to_ppi_control_information::DscpToPpiControlInformation,
error_indication_report::ErrorIndicationReport,
ip_multicast_addressing_info::IpMulticastAddressingInfo,
join_ip_multicast_information_within_usage_report::JoinIpMulticastInformationWithinUsageReport,
leave_ip_multicast_information_within_usage_report::LeaveIpMulticastInformationWithinUsageReport,
partial_failure_information::PartialFailureInformation,
peer_up_restart_report::PeerUpRestartReport,
remove_mar::RemoveMar,
remove_srr::RemoveSrr,
session_report::SessionReport,
ue_ip_address_pool_information::UeIpAddressPoolInformation,
updated_pdr::UpdatedPdr,
);
#[cfg(test)]
mod tests {
use super::*;
use crate::types::{Seid, Teid};
#[test]
fn test_reject_zero_length_ie() {
let malformed = vec![
0x00, 0x60, 0x00, 0x00, ];
let result = Ie::unmarshal(&malformed);
assert!(result.is_err());
let err = result.unwrap_err();
assert!(matches!(err, PfcpError::InvalidValue { .. }));
assert!(err.to_string().contains("Zero-length"));
assert!(err.to_string().contains("96"));
}
#[test]
fn test_reject_zero_length_vendor_specific_ie() {
let malformed = vec![
0x80, 0x01, 0x00, 0x00, 0x00, 0x0A, ];
let result = Ie::unmarshal(&malformed);
assert!(result.is_err());
let err = result.unwrap_err();
assert!(matches!(err, PfcpError::InvalidValue { .. }));
assert!(err.to_string().contains("Zero-length"));
}
#[test]
fn test_accept_valid_one_byte_ie() {
let valid = vec![
0x00, 0x13, 0x00, 0x01, 0x01, ];
let result = Ie::unmarshal(&valid);
assert!(result.is_ok());
let ie = result.unwrap();
assert_eq!(ie.ie_type, IeType::Cause);
assert_eq!(ie.payload.len(), 1);
assert_eq!(ie.payload[0], 1);
}
#[test]
fn test_security_dos_prevention() {
let attack_vectors = vec![
vec![0x00, 0x60, 0x00, 0x00], vec![0x00, 0x13, 0x00, 0x00], vec![0x00, 0x3C, 0x00, 0x00], vec![0x00, 0x39, 0x00, 0x00], ];
for malformed in attack_vectors {
let result = Ie::unmarshal(&malformed);
assert!(
result.is_err(),
"Should reject zero-length IE: {:?}",
malformed
);
}
}
#[test]
fn test_zero_length_allowlist_network_instance() {
let zero_length_ni = vec![
0x00, 0x16, 0x00, 0x00, ];
let result = Ie::unmarshal(&zero_length_ni);
assert!(result.is_ok(), "Network Instance should allow zero-length");
let ie = result.unwrap();
assert_eq!(ie.ie_type, IeType::NetworkInstance);
assert_eq!(ie.payload.len(), 0);
}
#[test]
fn test_zero_length_allowlist_apn_dnn() {
let zero_length_apn = vec![
0x00, 0x9F, 0x00, 0x00, ];
let result = Ie::unmarshal(&zero_length_apn);
assert!(result.is_ok(), "APN/DNN should allow zero-length");
let ie = result.unwrap();
assert_eq!(ie.ie_type, IeType::ApnDnn);
assert_eq!(ie.payload.len(), 0);
}
#[test]
fn test_zero_length_allowlist_forwarding_policy() {
let zero_length_fp = vec![
0x00, 0x29, 0x00, 0x00, ];
let result = Ie::unmarshal(&zero_length_fp);
assert!(result.is_ok(), "Forwarding Policy should allow zero-length");
let ie = result.unwrap();
assert_eq!(ie.ie_type, IeType::ForwardingPolicy);
assert_eq!(ie.payload.len(), 0);
}
#[test]
fn test_zero_length_rejected_for_non_allowlisted() {
let test_cases = vec![
(0x0018, "ApplicationId"), (0x0017, "SdfFilter"), (0x0014, "SourceInterface"), (0x001D, "Precedence"), (0x006C, "FarId"), ];
for (ie_type, name) in test_cases {
let zero_length_ie = vec![
(ie_type >> 8) as u8,
(ie_type & 0xFF) as u8,
0x00,
0x00, ];
let result = Ie::unmarshal(&zero_length_ie);
assert!(
result.is_err(),
"{} should reject zero-length (not in allowlist)",
name
);
let err = result.unwrap_err();
assert!(err.to_string().contains("Zero-length"));
}
}
#[test]
fn test_zero_length_update_far_scenario() {
use crate::ie::network_instance::NetworkInstance;
let clear_ni = NetworkInstance::new("");
let clear_ni_ie = clear_ni.to_ie();
let marshaled = clear_ni_ie.marshal();
assert_eq!(marshaled[0..2], [0x00, 0x16]); assert_eq!(marshaled[2..4], [0x00, 0x00]);
let unmarshaled = Ie::unmarshal(&marshaled);
assert!(
unmarshaled.is_ok(),
"Zero-length Network Instance should unmarshal successfully"
);
let ie = unmarshaled.unwrap();
assert_eq!(ie.payload.len(), 0);
assert_eq!(ie.ie_type, IeType::NetworkInstance);
let ni_result = NetworkInstance::unmarshal(&ie.payload);
assert!(ni_result.is_ok());
assert_eq!(ni_result.unwrap().instance, "");
}
#[test]
fn test_ie_type_from_u16_core_types() {
assert_eq!(IeType::from(1), IeType::CreatePdr);
assert_eq!(IeType::from(2), IeType::Pdi);
assert_eq!(IeType::from(3), IeType::CreateFar);
assert_eq!(IeType::from(19), IeType::Cause);
assert_eq!(IeType::from(56), IeType::PdrId);
assert_eq!(IeType::from(57), IeType::Fseid);
assert_eq!(IeType::from(60), IeType::NodeId);
assert_eq!(IeType::from(108), IeType::FarId);
assert_eq!(IeType::from(109), IeType::QerId);
}
#[test]
fn test_ie_type_from_u16_session_types() {
assert_eq!(IeType::from(8), IeType::CreatedPdr);
assert_eq!(IeType::from(9), IeType::UpdatePdr);
assert_eq!(IeType::from(10), IeType::UpdateFar);
assert_eq!(IeType::from(15), IeType::RemovePdr);
assert_eq!(IeType::from(16), IeType::RemoveFar);
assert_eq!(IeType::from(85), IeType::CreateBar);
assert_eq!(IeType::from(86), IeType::UpdateBar);
assert_eq!(IeType::from(87), IeType::RemoveBar);
assert_eq!(IeType::from(88), IeType::BarId);
}
#[test]
fn test_ie_type_from_u16_network_types() {
assert_eq!(IeType::from(20), IeType::SourceInterface);
assert_eq!(IeType::from(21), IeType::Fteid);
assert_eq!(IeType::from(22), IeType::NetworkInstance);
assert_eq!(IeType::from(42), IeType::DestinationInterface);
assert_eq!(IeType::from(84), IeType::OuterHeaderCreation);
assert_eq!(IeType::from(95), IeType::OuterHeaderRemoval);
assert_eq!(IeType::from(192), IeType::SourceIpAddress);
}
#[test]
fn test_ie_type_from_u16_qos_types() {
assert_eq!(IeType::from(25), IeType::GateStatus);
assert_eq!(IeType::from(26), IeType::Mbr);
assert_eq!(IeType::from(27), IeType::Gbr);
assert_eq!(IeType::from(29), IeType::Precedence);
assert_eq!(IeType::from(30), IeType::TransportLevelMarking);
}
#[test]
fn test_ie_type_from_u16_monitoring_types() {
assert_eq!(IeType::from(62), IeType::MeasurementMethod);
assert_eq!(IeType::from(63), IeType::UsageReportTrigger);
assert_eq!(IeType::from(66), IeType::VolumeMeasurement);
assert_eq!(IeType::from(67), IeType::DurationMeasurement);
assert_eq!(IeType::from(96), IeType::RecoveryTimeStamp);
}
#[test]
fn test_ie_type_from_u16_tsn_types() {
assert_eq!(IeType::from(194), IeType::CreateBridgeInfoForTsc);
assert_eq!(IeType::from(195), IeType::CreatedBridgeInfoForTsc);
assert_eq!(IeType::from(198), IeType::TsnBridgeId);
assert_eq!(IeType::from(206), IeType::TsnTimeDomainNumber);
}
#[test]
fn test_ie_type_from_u16_5g_types() {
assert_eq!(IeType::from(113), IeType::PdnType);
assert_eq!(IeType::from(159), IeType::ApnDnn);
assert_eq!(IeType::from(160), IeType::TgppInterfaceType);
assert_eq!(IeType::from(257), IeType::Snssai);
}
#[test]
fn test_ie_type_from_u16_unknown() {
assert_eq!(IeType::from(9999), IeType::Unknown);
assert_eq!(IeType::from(0), IeType::Unknown);
assert_eq!(IeType::from(65535), IeType::Unknown);
}
#[test]
fn test_ie_type_to_u16_round_trip() {
let test_types = vec![
IeType::CreatePdr,
IeType::Cause,
IeType::NodeId,
IeType::Fteid,
IeType::PdrId,
IeType::FarId,
IeType::Snssai,
IeType::SourceIpAddress,
];
for ie_type in test_types {
let as_u16 = ie_type as u16;
let back = IeType::from(as_u16);
assert_eq!(back, ie_type, "Round-trip failed for {:?}", ie_type);
}
}
#[test]
fn test_ie_new() {
let payload = vec![0x01, 0x02, 0x03];
let ie = Ie::new(IeType::Cause, payload.clone());
assert_eq!(ie.ie_type, IeType::Cause);
assert_eq!(ie.enterprise_id, None);
assert_eq!(ie.payload, payload);
assert_eq!(ie.child_ies.len(), 0);
assert!(!ie.is_vendor_specific());
}
#[test]
fn test_ie_new_vendor_specific() {
let payload = vec![0xAA, 0xBB];
let ie = Ie::new_vendor_specific(IeType::Unknown, 12345, payload.clone());
assert_eq!(ie.ie_type, IeType::Unknown);
assert_eq!(ie.enterprise_id, Some(12345));
assert_eq!(ie.payload, payload);
assert!(ie.is_vendor_specific());
}
#[test]
fn test_ie_new_grouped() {
let child1 = Ie::new(IeType::PdrId, vec![0x00, 0x01]);
let child2 = Ie::new(IeType::FarId, vec![0x00, 0x00, 0x00, 0x02]);
let grouped = Ie::new_grouped(IeType::CreatePdr, vec![child1.clone(), child2.clone()]);
assert_eq!(grouped.ie_type, IeType::CreatePdr);
assert_eq!(grouped.enterprise_id, None);
assert_eq!(grouped.child_ies.len(), 2);
let expected_payload = {
let mut v = Vec::new();
v.extend_from_slice(&child1.marshal());
v.extend_from_slice(&child2.marshal());
v
};
assert_eq!(grouped.payload, expected_payload);
}
#[test]
fn test_ie_from_marshal() {
use crate::ie::cause::{Cause, CauseValue};
use crate::ie::destination_interface::{DestinationInterface, Interface};
let cause = Cause::new(CauseValue::RequestAccepted);
let ie_from_array = Ie::from_marshal(IeType::Cause, cause.marshal());
assert_eq!(ie_from_array.ie_type, IeType::Cause);
assert_eq!(ie_from_array.payload, vec![1]);
let dest_if = DestinationInterface::new(Interface::Core);
let ie_from_vec = Ie::from_marshal(IeType::DestinationInterface, dest_if.marshal());
assert_eq!(ie_from_vec.ie_type, IeType::DestinationInterface);
assert_eq!(ie_from_vec.payload, vec![0x01]);
let ie_traditional = Ie::new(IeType::Cause, cause.marshal().to_vec());
assert_eq!(ie_from_array, ie_traditional);
}
#[test]
fn test_ie_len_simple() {
let ie = Ie::new(IeType::Cause, vec![0x01]);
assert_eq!(ie.len(), 5);
}
#[test]
fn test_ie_len_vendor_specific() {
let ie = Ie::new_vendor_specific(IeType::Unknown, 123, vec![0xAA, 0xBB]);
assert_eq!(ie.len(), 8);
}
#[test]
fn test_ie_is_empty() {
let empty = Ie::new(IeType::NetworkInstance, vec![]);
assert!(empty.is_empty());
let not_empty = Ie::new(IeType::Cause, vec![0x01]);
assert!(!not_empty.is_empty());
}
#[test]
fn test_ie_is_vendor_specific_with_enterprise_id() {
let ie = Ie::new_vendor_specific(IeType::Unknown, 100, vec![0x01]);
assert!(ie.is_vendor_specific());
}
#[test]
fn test_ie_is_vendor_specific_with_flag() {
let vendor_ie_bytes = vec![
0x80, 0x01, 0x00, 0x02, 0x00, 0x0A, ];
let ie = Ie::unmarshal(&vendor_ie_bytes).unwrap();
assert!(ie.is_vendor_specific());
assert_eq!(ie.enterprise_id, Some(10));
}
#[test]
fn test_ie_marshal_simple() {
let ie = Ie::new(IeType::Cause, vec![0x01]);
let marshaled = ie.marshal();
assert_eq!(marshaled[0..2], [0x00, 0x13]); assert_eq!(marshaled[2..4], [0x00, 0x01]); assert_eq!(marshaled[4], 0x01); }
#[test]
fn test_ie_marshal_vendor_specific() {
let ie = Ie::new_vendor_specific(IeType::Unknown, 12345, vec![0xAA, 0xBB]);
let marshaled = ie.marshal();
assert_eq!(marshaled[0..2], [0x00, 0x00]); assert_eq!(marshaled[2..4], [0x00, 0x04]); assert_eq!(marshaled[4..6], [0x30, 0x39]); assert_eq!(marshaled[6..8], [0xAA, 0xBB]); }
#[test]
fn test_ie_unmarshal_simple_round_trip() {
let original = Ie::new(IeType::PdrId, vec![0x00, 0x42]);
let marshaled = original.marshal();
let unmarshaled = Ie::unmarshal(&marshaled).unwrap();
assert_eq!(unmarshaled.ie_type, original.ie_type);
assert_eq!(unmarshaled.enterprise_id, original.enterprise_id);
assert_eq!(unmarshaled.payload, original.payload);
}
#[test]
fn test_ie_unmarshal_vendor_specific_round_trip() {
let vendor_ie_bytes = vec![
0x80, 0x01, 0x00, 0x05, 0x03, 0xE7, 0x01, 0x02, 0x03, ];
let unmarshaled = Ie::unmarshal(&vendor_ie_bytes).unwrap();
assert!(unmarshaled.is_vendor_specific());
assert_eq!(unmarshaled.enterprise_id, Some(999));
assert_eq!(unmarshaled.payload, vec![0x01, 0x02, 0x03]);
}
#[test]
fn test_ie_unmarshal_too_short() {
let short_buffer = vec![0x00, 0x13, 0x00]; let result = Ie::unmarshal(&short_buffer);
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
PfcpError::InvalidLength { .. }
));
}
#[test]
fn test_ie_unmarshal_payload_length_mismatch() {
let malformed = vec![
0x00, 0x13, 0x00, 0x05, 0x01, ];
let result = Ie::unmarshal(&malformed);
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
PfcpError::InvalidLength { .. }
));
}
#[test]
fn test_ie_unmarshal_vendor_specific_too_short() {
let malformed = vec![
0x80, 0x01, 0x00, 0x02, 0x00, ];
let result = Ie::unmarshal(&malformed);
assert!(result.is_err());
let err = result.unwrap_err();
assert!(matches!(err, PfcpError::InvalidLength { .. }));
}
#[test]
fn test_ie_as_u8() {
let ie = Ie::new(IeType::Cause, vec![0x42]);
assert_eq!(ie.as_u8().unwrap(), 0x42);
}
#[test]
fn test_ie_as_u8_empty_payload() {
let ie = Ie::new(IeType::NetworkInstance, vec![]);
let result = ie.as_u8();
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
PfcpError::InvalidLength { .. }
));
}
#[test]
fn test_ie_as_u16() {
let ie = Ie::new(IeType::PdrId, vec![0x12, 0x34]);
assert_eq!(ie.as_u16().unwrap(), 0x1234);
}
#[test]
fn test_ie_as_u16_too_short() {
let ie = Ie::new(IeType::PdrId, vec![0x12]);
let result = ie.as_u16();
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
PfcpError::InvalidLength { .. }
));
}
#[test]
fn test_ie_as_u32() {
let ie = Ie::new(IeType::FarId, vec![0x12, 0x34, 0x56, 0x78]);
assert_eq!(ie.as_u32().unwrap(), 0x12345678);
}
#[test]
fn test_ie_as_u32_too_short() {
let ie = Ie::new(IeType::FarId, vec![0x12, 0x34]);
let result = ie.as_u32();
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
PfcpError::InvalidLength { .. }
));
}
#[test]
fn test_ie_as_u64() {
let ie = Ie::new(
IeType::Fseid,
vec![0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0],
);
assert_eq!(ie.as_u64().unwrap(), 0x123456789ABCDEF0);
}
#[test]
fn test_ie_as_u64_too_short() {
let ie = Ie::new(IeType::Fseid, vec![0x12, 0x34, 0x56, 0x78]);
let result = ie.as_u64();
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
PfcpError::InvalidLength { .. }
));
}
#[test]
fn test_ie_as_string() {
let ie = Ie::new(
IeType::NetworkInstance,
b"internet.mnc001.mcc001.gprs".to_vec(),
);
assert_eq!(ie.as_string().unwrap(), "internet.mnc001.mcc001.gprs");
}
#[test]
fn test_ie_as_string_invalid_utf8() {
let ie = Ie::new(IeType::NetworkInstance, vec![0xFF, 0xFE, 0xFD]);
let result = ie.as_string();
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
PfcpError::InvalidValue { .. }
));
}
#[test]
fn test_ie_as_ies_simple() {
let child1 = Ie::new(IeType::PdrId, vec![0x00, 0x01]);
let child2 = Ie::new(IeType::Precedence, vec![0x00, 0x64]);
let mut grouped = Ie::new_grouped(IeType::CreatePdr, vec![child1, child2]);
let children = grouped.as_ies().unwrap();
assert_eq!(children.len(), 2);
assert_eq!(children[0].ie_type, IeType::PdrId);
assert_eq!(children[1].ie_type, IeType::Precedence);
}
#[test]
fn test_ie_as_ies_cached() {
let child = Ie::new(IeType::FarId, vec![0x00, 0x00, 0x00, 0x01]);
let mut grouped = Ie::new_grouped(IeType::CreateFar, vec![child]);
let children1 = grouped.as_ies().unwrap();
assert_eq!(children1.len(), 1);
let children2 = grouped.as_ies().unwrap();
assert_eq!(children2.len(), 1);
assert_eq!(children2[0].ie_type, IeType::FarId);
}
#[test]
fn test_ie_as_ies_empty_payload() {
let mut ie = Ie::new(IeType::CreatePdr, vec![]);
let children = ie.as_ies().unwrap();
assert_eq!(children.len(), 0);
}
#[test]
fn test_ie_as_ies_malformed_child() {
let mut ie = Ie::new(IeType::CreatePdr, vec![0x00, 0x38]); let result = ie.as_ies();
assert!(result.is_err());
assert!(matches!(
result.unwrap_err(),
PfcpError::InvalidLength { .. }
));
}
#[test]
fn test_ie_as_ies_nested() {
let inner_child = Ie::new(IeType::SourceInterface, vec![0x00]);
let inner_grouped = Ie::new_grouped(IeType::Pdi, vec![inner_child]);
let pdr_id = Ie::new(IeType::PdrId, vec![0x00, 0x01]);
let mut outer_grouped = Ie::new_grouped(IeType::CreatePdr, vec![pdr_id, inner_grouped]);
let children = outer_grouped.as_ies().unwrap();
assert_eq!(children.len(), 2);
assert_eq!(children[0].ie_type, IeType::PdrId);
assert_eq!(children[1].ie_type, IeType::Pdi);
let mut pdi = children[1].clone();
let nested_children = pdi.as_ies().unwrap();
assert_eq!(nested_children.len(), 1);
assert_eq!(nested_children[0].ie_type, IeType::SourceInterface);
}
#[test]
fn test_ie_large_payload() {
let large_payload = vec![0x42; 1000];
let ie = Ie::new(IeType::NetworkInstance, large_payload.clone());
let marshaled = ie.marshal();
let unmarshaled = Ie::unmarshal(&marshaled).unwrap();
assert_eq!(unmarshaled.payload, large_payload);
}
#[test]
fn test_ie_all_ie_types_round_trip() {
let test_types = vec![
(IeType::CreatePdr, vec![0x01, 0x02]),
(IeType::Cause, vec![0x01]),
(IeType::NodeId, vec![0x00, 0x01, 0x02, 0x03, 0x04]),
(IeType::Fseid, vec![0x01; 8]),
(IeType::Snssai, vec![0x01, 0x02, 0x03, 0x04]),
(IeType::SourceIpAddress, vec![0x01; 4]),
(IeType::RecoveryTimeStamp, vec![0x00, 0x00, 0x00, 0x01]),
];
for (ie_type, payload) in test_types {
let original = Ie::new(ie_type, payload);
let marshaled = original.marshal();
let unmarshaled = Ie::unmarshal(&marshaled).unwrap();
assert_eq!(
unmarshaled.ie_type, original.ie_type,
"Failed for {:?}",
ie_type
);
assert_eq!(
unmarshaled.payload, original.payload,
"Failed for {:?}",
ie_type
);
}
}
mod into_ie_tests {
use super::*;
use crate::ie::fseid::Fseid;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
#[test]
fn test_into_ie_tuple_fseid_ipv4() {
let seid = 0x123456789ABCDEFu64;
let ipv4 = Ipv4Addr::new(10, 0, 0, 1);
let ie = (seid, ipv4).into_ie();
assert_eq!(ie.ie_type, IeType::Fseid);
let fseid = Fseid::unmarshal(&ie.payload).unwrap();
assert_eq!(fseid.seid, Seid(seid));
assert_eq!(fseid.ipv4_address, Some(ipv4));
assert_eq!(fseid.ipv6_address, None);
}
#[test]
fn test_into_ie_tuple_fseid_ipv6() {
let seid = 0x123456789ABCDEFu64;
let ipv6 = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
let ie = (seid, ipv6).into_ie();
assert_eq!(ie.ie_type, IeType::Fseid);
let fseid = Fseid::unmarshal(&ie.payload).unwrap();
assert_eq!(fseid.seid, Seid(seid));
assert_eq!(fseid.ipv4_address, None);
assert_eq!(fseid.ipv6_address, Some(ipv6));
}
#[test]
fn test_into_ie_tuple_fseid_ipaddr_v4() {
let seid = 0x123456789ABCDEFu64;
let ip = IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1));
let ie = (seid, ip).into_ie();
assert_eq!(ie.ie_type, IeType::Fseid);
let fseid = Fseid::unmarshal(&ie.payload).unwrap();
assert_eq!(fseid.seid, Seid(seid));
assert!(fseid.ipv4_address.is_some());
assert!(fseid.ipv6_address.is_none());
}
#[test]
fn test_into_ie_tuple_fseid_ipaddr_v6() {
let seid = 0x123456789ABCDEFu64;
let ip = IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
let ie = (seid, ip).into_ie();
assert_eq!(ie.ie_type, IeType::Fseid);
let fseid = Fseid::unmarshal(&ie.payload).unwrap();
assert_eq!(fseid.seid, Seid(seid));
assert!(fseid.ipv4_address.is_none());
assert!(fseid.ipv6_address.is_some());
}
#[test]
fn test_into_ie_tuple_fseid_round_trip() {
let seid = 0xFEDCBA9876543210u64;
let ipv4 = Ipv4Addr::new(192, 168, 1, 1);
let ie = (seid, ipv4).into_ie();
let fseid = Fseid::unmarshal(&ie.payload).unwrap();
assert_eq!(fseid.seid, Seid(seid));
assert_eq!(fseid.ipv4_address, Some(ipv4));
let explicit_fseid = Fseid::new(seid, Some(ipv4), None);
assert_eq!(fseid, explicit_fseid);
}
#[test]
fn test_into_ie_tuple_fteid_ipv4() {
use crate::ie::f_teid::Fteid;
let teid = 0x12345678u32;
let ip = Ipv4Addr::new(192, 168, 1, 1);
let ie = (teid, ip).into_ie();
assert_eq!(ie.ie_type, IeType::Fteid);
let fteid = Fteid::unmarshal(&ie.payload).unwrap();
assert_eq!(fteid.teid, Teid(teid));
assert_eq!(fteid.ipv4_address, Some(ip));
assert_eq!(fteid.ipv6_address, None);
assert!(fteid.v4);
assert!(!fteid.v6);
}
#[test]
fn test_into_ie_tuple_fteid_ipv6() {
use crate::ie::f_teid::Fteid;
let teid = 0x87654321u32;
let ip = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1);
let ie = (teid, ip).into_ie();
assert_eq!(ie.ie_type, IeType::Fteid);
let fteid = Fteid::unmarshal(&ie.payload).unwrap();
assert_eq!(fteid.teid, Teid(teid));
assert_eq!(fteid.ipv4_address, None);
assert_eq!(fteid.ipv6_address, Some(ip));
assert!(!fteid.v4);
assert!(fteid.v6);
}
#[test]
fn test_into_ie_tuple_fteid_ipaddr_v4() {
use crate::ie::f_teid::Fteid;
let teid = 0xABCD1234u32;
let ipv4 = Ipv4Addr::new(10, 0, 0, 1);
let ip: IpAddr = IpAddr::V4(ipv4);
let ie = (teid, ip).into_ie();
assert_eq!(ie.ie_type, IeType::Fteid);
let fteid = Fteid::unmarshal(&ie.payload).unwrap();
assert_eq!(fteid.teid, Teid(teid));
assert_eq!(fteid.ipv4_address, Some(ipv4));
assert_eq!(fteid.ipv6_address, None);
}
#[test]
fn test_into_ie_tuple_fteid_ipaddr_v6() {
use crate::ie::f_teid::Fteid;
let teid = 0xDEADBEEFu32;
let ipv6 = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1);
let ip: IpAddr = IpAddr::V6(ipv6);
let ie = (teid, ip).into_ie();
assert_eq!(ie.ie_type, IeType::Fteid);
let fteid = Fteid::unmarshal(&ie.payload).unwrap();
assert_eq!(fteid.teid, Teid(teid));
assert_eq!(fteid.ipv4_address, None);
assert_eq!(fteid.ipv6_address, Some(ipv6));
}
#[test]
fn test_into_ie_tuple_fteid_round_trip() {
use crate::ie::f_teid::Fteid;
let teid = 0xCAFEBABEu32;
let ipv4 = Ipv4Addr::new(172, 16, 0, 1);
let ie = (teid, ipv4).into_ie();
let fteid = Fteid::unmarshal(&ie.payload).unwrap();
assert_eq!(fteid.teid, Teid(teid));
assert_eq!(fteid.ipv4_address, Some(ipv4));
let explicit_fteid = Fteid::new(true, false, teid, Some(ipv4), None, 0);
assert_eq!(fteid, explicit_fteid);
}
#[test]
fn test_into_ie_tuple_ue_ip_dual_stack() {
use crate::ie::ue_ip_address::UeIpAddress;
let ipv4 = Ipv4Addr::new(10, 1, 2, 3);
let ipv6 = Ipv6Addr::new(0x2001, 0xdb8, 0xabc, 0xdef, 0, 0, 0, 1);
let ie = (ipv4, ipv6).into_ie();
assert_eq!(ie.ie_type, IeType::UeIpAddress);
let ue_ip = UeIpAddress::unmarshal(&ie.payload).unwrap();
assert_eq!(ue_ip.ipv4_address, Some(ipv4));
assert_eq!(ue_ip.ipv6_address, Some(ipv6));
assert!(ue_ip.v4);
assert!(ue_ip.v6);
}
#[test]
fn test_into_ie_tuple_ue_ip_round_trip() {
use crate::ie::ue_ip_address::UeIpAddress;
let ipv4 = Ipv4Addr::new(192, 0, 2, 1);
let ipv6 = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 42);
let ie = (ipv4, ipv6).into_ie();
let ue_ip = UeIpAddress::unmarshal(&ie.payload).unwrap();
assert_eq!(ue_ip.ipv4_address, Some(ipv4));
assert_eq!(ue_ip.ipv6_address, Some(ipv6));
let explicit_ue_ip = UeIpAddress::new(Some(ipv4), Some(ipv6));
assert_eq!(ue_ip, explicit_ue_ip);
}
}
mod grouped_ie_helpers {
use super::*;
#[test]
fn test_marshal_ies_empty() {
let ies: Vec<Ie> = vec![];
let result = marshal_ies(&ies);
assert_eq!(result.len(), 0);
}
#[test]
fn test_marshal_ies_single() {
let ies = vec![Ie::new(IeType::PdrId, vec![0x00, 0x01])];
let result = marshal_ies(&ies);
assert!(result.len() >= 4);
let expected_len: usize = ies.iter().map(|ie| ie.len() as usize).sum();
assert_eq!(result.len(), expected_len);
}
#[test]
fn test_marshal_ies_multiple() {
let ies = vec![
Ie::new(IeType::PdrId, vec![0x00, 0x01]),
Ie::new(IeType::FarId, vec![0x00, 0x00, 0x00, 0x02]),
Ie::new(IeType::Precedence, vec![0x00, 0x00, 0x00, 0x64]),
];
let result = marshal_ies(&ies);
let expected_len: usize = ies.iter().map(|ie| ie.len() as usize).sum();
assert_eq!(result.len(), expected_len);
}
#[test]
fn test_marshal_ies_round_trip() {
let original_ies = vec![
Ie::new(IeType::PdrId, vec![0x00, 0x01]),
Ie::new(IeType::FarId, vec![0x00, 0x00, 0x00, 0x02]),
];
let marshaled = marshal_ies(&original_ies);
let mut parsed_ies = vec![];
for ie_result in IeIterator::new(&marshaled) {
parsed_ies.push(ie_result.unwrap());
}
assert_eq!(parsed_ies.len(), original_ies.len());
assert_eq!(parsed_ies[0].ie_type, IeType::PdrId);
assert_eq!(parsed_ies[1].ie_type, IeType::FarId);
}
#[test]
fn test_ie_iterator_empty() {
let payload: Vec<u8> = vec![];
let mut iter = IeIterator::new(&payload);
assert!(iter.next().is_none());
}
#[test]
fn test_ie_iterator_single() {
let ie = Ie::new(IeType::PdrId, vec![0x00, 0x01]);
let payload = ie.marshal();
let mut count = 0;
for ie_result in IeIterator::new(&payload) {
let parsed_ie = ie_result.unwrap();
assert_eq!(parsed_ie.ie_type, IeType::PdrId);
assert_eq!(parsed_ie.payload, vec![0x00, 0x01]);
count += 1;
}
assert_eq!(count, 1);
}
#[test]
fn test_ie_iterator_multiple() {
let ies = vec![
Ie::new(IeType::PdrId, vec![0x00, 0x01]),
Ie::new(IeType::FarId, vec![0x00, 0x00, 0x00, 0x02]),
Ie::new(IeType::Precedence, vec![0x00, 0x00, 0x00, 0x64]),
];
let payload = marshal_ies(&ies);
let mut count = 0;
let expected_types = [IeType::PdrId, IeType::FarId, IeType::Precedence];
for ie_result in IeIterator::new(&payload) {
let ie = ie_result.unwrap();
assert_eq!(ie.ie_type, expected_types[count]);
count += 1;
}
assert_eq!(count, 3);
}
#[test]
fn test_ie_iterator_with_question_mark_operator() {
fn parse_ies(payload: &[u8]) -> Result<Vec<IeType>, PfcpError> {
let mut types = vec![];
for ie_result in IeIterator::new(payload) {
let ie = ie_result?; types.push(ie.ie_type);
}
Ok(types)
}
let ies = vec![
Ie::new(IeType::PdrId, vec![0x00, 0x01]),
Ie::new(IeType::FarId, vec![0x00, 0x00, 0x00, 0x02]),
];
let payload = marshal_ies(&ies);
let types = parse_ies(&payload).unwrap();
assert_eq!(types, vec![IeType::PdrId, IeType::FarId]);
}
#[test]
fn test_ie_iterator_error_truncated() {
let payload = vec![0x00, 0x01];
let mut iter = IeIterator::new(&payload);
match iter.next() {
Some(Err(_)) => (), other => panic!("Expected error for truncated payload, got: {:?}", other),
}
assert!(iter.next().is_none());
}
#[test]
fn test_ie_iterator_stops_on_error() {
let valid_ie = Ie::new(IeType::PdrId, vec![0x00, 0x01]);
let mut payload = valid_ie.marshal();
payload.extend_from_slice(&[0x00, 0x01]);
let mut count = 0;
let mut error_found = false;
for ie_result in IeIterator::new(&payload) {
match ie_result {
Ok(_) => count += 1,
Err(_) => {
error_found = true;
break;
}
}
}
assert_eq!(count, 1, "Should parse one valid IE");
assert!(error_found, "Should encounter error on truncated IE");
}
#[test]
fn test_marshal_ies_preserves_order() {
let ies = vec![
Ie::new(IeType::PdrId, vec![0x00, 0x01]),
Ie::new(IeType::Precedence, vec![0x00, 0x00, 0x00, 0x64]),
Ie::new(IeType::FarId, vec![0x00, 0x00, 0x00, 0x02]),
];
let marshaled = marshal_ies(&ies);
let mut types = vec![];
for ie_result in IeIterator::new(&marshaled) {
types.push(ie_result.unwrap().ie_type);
}
assert_eq!(
types,
vec![IeType::PdrId, IeType::Precedence, IeType::FarId]
);
}
#[test]
fn test_ie_iterator_offset_tracking() {
let ies = vec![
Ie::new(IeType::PdrId, vec![0x00, 0x01]),
Ie::new(IeType::FarId, vec![0x00, 0x00, 0x00, 0x02]),
];
let payload = marshal_ies(&ies);
let mut iter = IeIterator::new(&payload);
assert_eq!(iter.offset, 0);
let ie1 = iter.next().unwrap().unwrap();
let ie1_len = ie1.len() as usize;
assert_eq!(iter.offset, ie1_len);
let ie2 = iter.next().unwrap().unwrap();
assert_eq!(iter.offset, ie1_len + ie2.len() as usize);
assert_eq!(iter.offset, payload.len());
assert!(iter.next().is_none());
}
}
#[test]
fn test_parse_cause() {
use cause::{Cause, CauseValue};
let ie = Ie::new(IeType::Cause, vec![1]);
let cause = ie.parse::<Cause>().unwrap();
assert_eq!(cause.value, CauseValue::RequestAccepted);
}
#[test]
fn test_parse_cause_error_on_empty() {
use cause::Cause;
let ie = Ie::new(IeType::Cause, vec![]);
assert!(ie.parse::<Cause>().is_err());
}
#[test]
fn test_parse_pdr_id() {
use pdr_id::PdrId;
let original = PdrId::new(42);
let ie = original.to_ie();
let parsed = ie.parse::<PdrId>().unwrap();
assert_eq!(parsed, original);
}
#[test]
fn test_parse_far_id() {
use far_id::FarId;
let original = FarId::new(7);
let ie = original.to_ie();
let parsed = ie.parse::<FarId>().unwrap();
assert_eq!(parsed, original);
}
#[test]
fn test_parse_node_id() {
use node_id::NodeId;
let original = NodeId::new_ipv4("192.168.1.1".parse().unwrap());
let ie = original.to_ie();
let parsed = ie.parse::<NodeId>().unwrap();
assert_eq!(parsed, original);
}
#[test]
fn test_parse_recovery_time_stamp() {
use std::time::Duration;
use std::time::UNIX_EPOCH;
let original = RecoveryTimeStamp::new(UNIX_EPOCH + Duration::from_secs(1_700_000_000));
let ie = original.to_ie();
let parsed = ie.parse::<RecoveryTimeStamp>().unwrap();
assert_eq!(
parsed
.timestamp
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs(),
original
.timestamp
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs(),
);
}
#[test]
fn test_parse_works_on_any_ie_reference() {
use cause::{Cause, CauseValue};
let ie = Ie::new(IeType::Cause, vec![64]);
let cause = ie.parse::<Cause>().unwrap();
assert_eq!(cause.value, CauseValue::RequestRejected);
let cause_ref = ie.parse::<Cause>().unwrap();
assert_eq!(cause_ref.value, CauseValue::RequestRejected);
}
}