oxirush_gtp_u/lib.rs
1//! GTP-U for the user plane of 5G and 4G, per 3GPP TS 29.281, with the PDU
2//! Session Container of TS 38.415: a codec, an endpoint for the tunnels of a
3//! base station, a UPF to test against, Linux TUN devices and an eBPF fast
4//! path.
5//!
6//! ```rust
7//! use oxirush_gtp_u::{DownlinkPduSessionInformation, Packet, PduSessionContainer};
8//!
9//! fn main() -> Result<(), Box<dyn std::error::Error>> {
10//! // An uplink G-PDU of QoS flow 9, as a gNB sends it on N3: the header,
11//! // the PDU Session Container, then the IP packet
12//! let uplink = Packet::uplink(0x1234_5678, 9, b"an IP packet".as_slice());
13//! let bytes = uplink.encode()?;
14//! println!("{:02x?}", &bytes[..16]);
15//!
16//! // Decode it. The payload stays in the datagram
17//! let decoded = Packet::decode_borrowed(&bytes)?;
18//! println!("TEID {:#x}, QFI {:?}", decoded.teid, decoded.qfi());
19//! println!("{:?}", String::from_utf8_lossy(decoded.payload));
20//!
21//! // A downlink G-PDU whose container has more than a QFI
22//! let mut information = DownlinkPduSessionInformation::new(9);
23//! information.rqi = true;
24//! let downlink = Packet::g_pdu(0x9abc_def0, b"an IP packet".as_slice())
25//! .with_pdu_session_container(PduSessionContainer::Downlink(information));
26//! let decoded = Packet::decode(&downlink.encode()?)?;
27//! if let Some(PduSessionContainer::Downlink(information)) = decoded.pdu_session_container() {
28//! println!("QFI {}, RQI {}", information.qfi, information.rqi);
29//! }
30//! Ok(())
31//! }
32//! ```
33//!
34//! ```text
35//! [34, ff, 00, 14, 12, 34, 56, 78, 00, 00, 00, 85, 01, 10, 09, 00]
36//! TEID 0x12345678, QFI Some(9)
37//! "an IP packet"
38//! QFI 9, RQI true
39//! ```
40//!
41//! # Tasks
42//!
43//! The [README](https://github.com/linouxis9/oxirush-gtp-u#readme) has a
44//! program for each, with what it prints.
45//!
46//! | Task | Items |
47//! |------|-------|
48//! | Encode and decode a G-PDU | [`Packet`], [`Packet::uplink`], [`Packet::decode_borrowed`], [`PduSessionContainer`] |
49//! | Carry a PDU session between a gNB and the test UPF | [`Endpoint`], [`Endpoint::install`], [`Endpoint::send`], [`upf_sim::UpfSimulator`], [`upf_sim::Session`], [`ipv4_udp`] |
50//! | Supervise the path to a peer | [`Endpoint::echo`], [`Endpoint::supervise`], [`Endpoint::path_state`], [`Endpoint::path_events`], [`PathEvent`] |
51//! | Answer a peer: Echo and Error Indication | [`Packet::echo_request`], [`InformationElement`] |
52//! | Read and write extension headers | [`ExtensionHeader`], [`ExtensionHeaders`], [`ExtensionHeaderType`] |
53//! | The headers of a handover | [`ExtensionHeader::PdcpPduNumber`], [`Packet::end_marker`] |
54//! | Give a tunnel a TUN, on Linux | [`tun::TunConfig`], [`tun::Routing`], [`Endpoint::attach_tun`] |
55//! | Carry the tunnel in the kernel, on Linux | [`ebpf::FastPath`], [`Endpoint::set_fast_path`] |
56//!
57// Without its feature an item of the tasks is plain text: the links are checked in the
58// build of every feature on Linux, which docs.rs makes.
59#![cfg_attr(
60 not(all(target_os = "linux", feature = "ebpf")),
61 allow(rustdoc::broken_intra_doc_links)
62)]
63//!
64//! It is made for simulators and test tools. It has no control plane: tunnels
65//! are set up by calls, with the identifiers and addresses that NGAP, S1AP or
66//! PFCP would negotiate.
67//!
68//! # Where things are
69//!
70//! | Part | Feature | Needs |
71//! | ---- | ------- | ----- |
72//! | The codec ([`Packet`], [`ExtensionHeader`], [`InformationElement`]) and the IPv4 helpers | none | no dependency |
73//! | [`Endpoint`], [`upf_sim`] | `endpoint`, the default | a Tokio runtime |
74//! | [`tun`], and `attach_tun` of [`Endpoint`] and [`UpfSimulator`](upf_sim::UpfSimulator) | `tun` | Linux, `CAP_NET_ADMIN` |
75//! | [`ebpf`] | `ebpf` | Linux 6.6, `CAP_BPF` and `CAP_NET_ADMIN` |
76//! | `Serialize` and `Deserialize` for [`RemoteTunnel`] | `serde` | |
77//! | The `oxirush-upf-sim` program | `cli` | |
78//!
79//! `ebpf` brings `tun`, and `tun`, `serde` and `cli` bring `endpoint`. The
80//! `tun` and `ebpf` modules exist on Linux only; elsewhere their features build
81//! and add nothing to `endpoint`. So does `ebpf` where the programs cannot run: on an
82//! architecture that their loader, aya, does not build for, such as 32-bit
83//! x86, and on a big-endian one, such as s390x, as their object is for
84//! little-endian eBPF. It runs on 64-bit x86, ARM, AArch64, RISC-V 64,
85//! LoongArch 64, and little-endian MIPS and PowerPC 64. The reference of each
86//! part is with it: [`Endpoint`], and the modules [`upf_sim`], [`tun`] and [`ebpf`].
87//!
88//! # Codec
89//!
90//! [`Packet`] has every header field of TS 29.281 §5.1, the chain of extension
91//! headers and the payload. There are constructors for G-PDU, Echo Request and
92//! Response, Error Indication, Supported Extension Headers Notification and End
93//! Marker; [`Packet::new`] and [`InformationElement::encode_all`] build any
94//! other message.
95//!
96//! Every extension header of TS 29.281 V19.2.0 §5.2.2 is a variant of
97//! [`ExtensionHeader`]. The PDU Session Container has the downlink and uplink
98//! PDU Session Information of TS 38.415 V19.1.0 §5.5.2, with the QoS
99//! monitoring, sequence number, delay and congestion fields, the downlink
100//! Burst Size and Time To Next Burst, and the uplink Available Bitrates. The
101//! PDCP PDU Number, the long one and the Service Class Indicator are their
102//! numbers. The PDU Set Information Container has the downlink PDU Set
103//! Information of TS 38.415 §6.5.2. The RAN Container, the Xw RAN Container
104//! and the NR RAN Container are the octets of a frame of TS 36.425, TS 36.465
105//! or TS 38.425, which the crate does not read.
106//!
107//! The numbers that say what a message, an extension header, an information
108//! element or a cause is are types that know the names of the specification:
109//! [`MessageType`], [`ExtensionHeaderType`], [`InformationElementType`] and
110//! [`Cause`]. `Debug` prints these names, a TEID in hexadecimal, and a payload
111//! or a value that is kept as received as its length and all its octets in
112//! hexadecimal.
113//!
114//! Decoding follows the receiver rules of §5.1: the flags decide which
115//! optional fields are read and the spare bit is ignored. Extension headers,
116//! TLV information elements and uplink New IEs that have no type of their own
117//! are kept as received. A TV information element imported from TS 29.060 is
118//! kept when its fixed length is known; an unknown TV type is an error. What
119//! decodes encodes to a message that decodes to the same value.
120//!
121//! [`Packet::extension_headers`] is an [`ExtensionHeaders`], the chain in its
122//! order on the wire: a slice to read and to change, `push` to add a header,
123//! and `From` a `Vec` and back for the rest. It keeps its first header in the
124//! list itself. A message without extension header, or with one, such as the
125//! PDU Session Container of a G-PDU on N3, is decoded and made without an
126//! allocation; a second header allocates the list, and a header or a PDU type
127//! that is kept as received allocates its octets.
128//!
129//! `Packet<P>` takes any payload that is `AsRef<[u8]>`, `Vec<u8>` by default.
130//! [`Packet::decode_borrowed`] returns a `Packet<&[u8]>` whose payload stays
131//! in the datagram, and `into_owned` copies it. `encoded_len` gives the wire
132//! length without encoding. `encode_into` appends to a `Vec<u8>` and leaves it
133//! as it was on an error. The codec's [`Error`] names the [`Part`] of the
134//! message that is wrong and has the numbers that disagree. It converts into
135//! a `std::io::Error`, for `?` next to an endpoint's calls.
136//!
137//! [`ipv4_udp`] and [`ipv4_icmp_echo_request`] build inner packets, and
138//! [`parse_ipv4_udp`] and [`parse_ipv4_icmp_echo`] read them, to exercise a
139//! tunnel without a TUN. They are IPv4 only; any payload, IPv6 included, is
140//! carried as it is.
141//!
142//! # What it covers
143//!
144//! | What | API | Specification |
145//! |------|-----|---------------|
146//! | Messages | `Packet`: every header field, the chain of extension headers, the information elements, and constructors for G-PDU, Echo Request and Response, Error Indication, Supported Extension Headers Notification and End Marker | TS 29.281 §5, §7 and §8 |
147//! | Extension headers | `ExtensionHeader`: the UDP Port, the PDCP PDU Number and the long one, the Service Class Indicator, the RAN, Xw RAN and NR RAN containers as octets, and the two below; a header of another type is kept as octets | TS 29.281 §5.2 |
148//! | PDU Session Container | `PduSessionContainer`: the downlink and the uplink PDU Session Information, with their QoS monitoring, sequence number, delay and congestion fields | TS 38.415 §5.5.2 |
149//! | PDU Set Information Container | `PduSetInformationContainer`: the downlink PDU Set Information | TS 38.415 §6.5.2 |
150//! | Tunnels of a gNB or an eNB | `Endpoint`: tunnels by UE and PDU session or E-RAB, the replies that a node owes its peer, Echo Requests and the supervision of a path | TS 29.281 §4.4, §7 and §11, TS 23.007 §20.3 |
151//! | A UPF to test against | `upf_sim::UpfSimulator` and the `oxirush-upf-sim` program: sessions, an echo service, an End Marker on a path switch | |
152//! | Linux as the device or as N6 | `tun::TunPort`, `Endpoint::attach_tun`, `UpfSimulator::attach_tun` | |
153//! | The tunnels in the kernel | `ebpf::FastPath` | |
154//! | Inner packets for tests | `ipv4_udp`, `ipv4_icmp_echo_request` and their parsers | |
155//!
156//! # Limits
157//!
158//! | Subject | Limit |
159//! |---------|-------|
160//! | Control plane | None: no NGAP, S1AP or PFCP. A call gives a tunnel its TEIDs and addresses. |
161//! | Authentication | GTP-U has none: anyone who reaches a socket can send on its tunnels. |
162//! | A UPF for real traffic | The test UPF serves the sessions that calls give it, with an echo service or a TUN. It has no PFCP, QoS or charging. |
163//! | Other GTP | GTP' and the versions 0 and 2 are refused, as `UnsupportedVersion`. |
164//! | IPv6 in the helpers, the TUN routing and the fast path | They are IPv4. The codec and the endpoint carry any payload, and an endpoint binds an IPv4 or an IPv6 address. |
165//! | Transport QoS and load balancing | Every G-PDU, through the socket or the fast path, has DSCP 0 and source port 2152. TS 29.281 §4.4.1 asks for the DSCP of the QoS flow's 5QI, which a call does not give, and §4.4.2.0 for source ports that vary, which one socket cannot have. |
166//! | Portability | `tun` and `ebpf` are Linux only, and `ebpf` adds nothing on 32-bit x86, which aya does not build for, and on big-endian architectures. |
167//!
168//! # Terms
169//!
170//! | Term | Meaning |
171//! |------|---------|
172//! | UE, gNB, eNB | The device (User Equipment), and the base station of 5G and of 4G |
173//! | UPF | User Plane Function: the node of the 5G core network that carries the traffic of the devices |
174//! | N3, S1-U, N6 | The interface between a gNB and a UPF, the one between an eNB and the gateway of a 4G core network, and the one between a UPF and the network that the devices reach |
175//! | Tunnel | The path of one PDU session of 5G, or of one bearer of 4G (an E-RAB), between two GTP-U nodes |
176//! | TEID | Tunnel Endpoint Identifier: the 32 bits in a GTP-U header that name the tunnel to the node that receives the message. Each end chooses the one it receives on |
177//! | G-PDU | The GTP-U message that carries one packet of a device, here an IP packet |
178//! | QFI | QoS Flow Identifier: the 6 bits that name the QoS flow of a packet in a 5G tunnel |
179//! | PDU Session Container | The extension header of a G-PDU that carries the QFI on N3 (TS 38.415) |
180//! | Echo, Error Indication, End Marker | The messages with which GTP-U nodes test a path, refuse a G-PDU of an unknown tunnel and close the old path of a handover |
181//! | TUN | A network interface of Linux whose packets a program reads and writes |
182//! | TCX | The attachment of eBPF programs to the ingress and the egress of an interface, since Linux 6.6 |
183//!
184//! # Specifications
185//!
186//! - 3GPP TS 29.281: GTPv1-U (header, extension headers, messages, information
187//! elements, path management)
188//! - 3GPP TS 38.415: NG-RAN PDU Session User Plane protocol (PDU Session
189//! Container, PDU Set Information Container)
190//! - 3GPP TS 29.060: imported TV information elements and receive rules
191//! - 3GPP TS 23.007: the supervision of a path (§20.3)
192//!
193//! # Source layout
194//!
195//! ```text
196//! src/
197//! ├── packet.rs owned and borrowed messages (TS 29.281 §5.1, §6, §7)
198//! ├── types.rs message, header and element types, and causes, by name
199//! ├── extension.rs extension headers and PDU Session Container (TS 38.415)
200//! ├── pdu_set.rs PDU Set Information Container (TS 38.415)
201//! ├── headers.rs the list of the extension headers of a message
202//! ├── ie.rs, error.rs information elements and codec errors
203//! ├── ipv4.rs, icmp.rs inner IPv4 UDP and ICMP Echo packets
204//! ├── datagram.rs, path.rs shared UDP receive and path management (endpoint)
205//! ├── limit.rs the limits of replies and log lines (endpoint)
206//! ├── endpoint.rs gNB endpoint and forwarding (endpoint)
207//! ├── endpoint/paths.rs Echo Requests, path supervision, peers' notifications (endpoint)
208//! ├── endpoint/routes.rs tunnel identity, route indexes and TUNs (endpoint)
209//! ├── stats.rs receive/drop counters (endpoint)
210//! ├── upf_sim.rs test UPF and forwarding (endpoint)
211//! ├── upf_sim/sessions.rs session generations and handover state (endpoint)
212//! ├── tun.rs public TUN API (tun)
213//! ├── tun/device.rs TUN descriptor and packet I/O (tun)
214//! ├── tun/routing.rs routing ownership and cleanup (tun)
215//! ├── tun/error.rs contextual I/O errors (tun)
216//! ├── netlink.rs rtnetlink operations (tun)
217//! ├── ebpf.rs loader of the fast path and its tunnels (ebpf)
218//! ├── ebpf/layout.rs map layouts shared with the programs (ebpf)
219//! ├── ebpf/programs.rs the TCX programs: uplink, encap, decap
220//! ├── ebpf/gtpu.o their object, built by ../ebpf (ebpf)
221//! └── bin/oxirush-upf-sim.rs
222//! ebpf/ what builds programs.rs for eBPF: build.sh and its manifest
223//! examples/ the programs of the README
224//! benches/ the benchmarks, a package of their own
225//! ```
226//!
227//! # The OxiRush family
228//!
229//! - [oxirush-utils](https://docs.rs/oxirush-utils): the 3GPP identities, and the JSON tree with its paths that the others share.
230//! - [oxirush-aper](https://docs.rs/oxirush-aper): aligned PER, the runtime of the NGAP and S1AP codecs.
231//! - [oxirush-nas](https://docs.rs/oxirush-nas): the NAS messages of 5GS and EPS.
232//! - [oxirush-security](https://docs.rs/oxirush-security): NAS security, AKA and the derivation of keys.
233//! - [oxirush-ngap](https://docs.rs/oxirush-ngap): NGAP, between a gNB and an AMF.
234//! - [oxirush-s1ap](https://docs.rs/oxirush-s1ap): S1AP, between an eNB and an MME.
235//! - [oxirush-gtp-u](https://docs.rs/oxirush-gtp-u): GTP-U tunnels, with a test UPF.
236//! - [oxirush-sctp](https://docs.rs/oxirush-sctp): SCTP sockets, which carry NGAP and S1AP.
237#![cfg_attr(docsrs, feature(doc_cfg))]
238#![deny(unsafe_code)]
239#![warn(missing_docs)]
240
241mod error;
242mod extension;
243mod headers;
244mod icmp;
245mod ie;
246mod ipv4;
247mod packet;
248mod pdu_set;
249mod types;
250
251#[cfg(feature = "endpoint")]
252mod datagram;
253// The `ebpf` feature on Linux, on a little-endian architecture of aya: see
254// build.rs.
255#[cfg(fast_path)]
256#[cfg_attr(docsrs, doc(cfg(all(target_os = "linux", feature = "ebpf"))))]
257#[allow(unsafe_code)]
258pub mod ebpf;
259#[cfg(feature = "endpoint")]
260mod endpoint;
261#[cfg(feature = "endpoint")]
262mod limit;
263#[cfg(all(target_os = "linux", feature = "tun"))]
264#[allow(unsafe_code)]
265mod netlink;
266#[cfg(feature = "endpoint")]
267mod path;
268#[cfg(feature = "endpoint")]
269mod stats;
270#[cfg(all(target_os = "linux", feature = "tun"))]
271#[allow(unsafe_code)]
272pub mod tun;
273#[cfg(feature = "endpoint")]
274pub mod upf_sim;
275
276#[cfg(feature = "endpoint")]
277pub use endpoint::{Endpoint, PathEvent, PathState, PathTimers, ReceivedPacket, RemoteTunnel};
278pub use error::{Error, Expected, Part};
279pub use extension::{
280 DownlinkPduSessionInformation, ExtensionHeader, PduSessionContainer, UnknownNewIes,
281 UplinkPduSessionInformation, UplinkTimeStamps,
282};
283pub use headers::{ExtensionHeaders, ExtensionHeadersIntoIter};
284pub use icmp::{
285 EchoKind, IcmpEcho, ipv4_icmp_echo_reply, ipv4_icmp_echo_request, parse_ipv4_icmp_echo,
286};
287pub use ie::InformationElement;
288pub use ipv4::{ipv4_udp, parse_ipv4_udp};
289pub use packet::Packet;
290pub use pdu_set::{DownlinkPduSetInformation, PduSetInformationContainer};
291#[cfg(feature = "endpoint")]
292pub use stats::ReceiveStats;
293pub use types::{Cause, ExtensionHeaderType, InformationElementType, MessageType};
294
295/// The UDP port of GTP-U.
296pub const PORT: u16 = 2152;