turmoil_net/kernel/packet.rs
1//! Structured packet types.
2//!
3//! Packets are not byte-encoded — the fields carry the same demux
4//! information (src/dst addrs, ports, TCP flags/seq/ack) a real kernel
5//! would read from IP + transport headers, but as typed data. This
6//! preserves state-machine fidelity without a parser. Byte-level framing
7//! can be added later if packet-corruption fault injection is needed.
8//!
9//! Header sizes below are used for MTU accounting only — no bytes
10//! actually exist on the wire.
11
12use std::net::IpAddr;
13
14use bytes::Bytes;
15
16/// IPv4 header size in bytes, no options.
17pub const IPV4_HEADER_SIZE: u16 = 20;
18/// IPv6 header size in bytes, no extension headers.
19pub const IPV6_HEADER_SIZE: u16 = 40;
20/// UDP header size in bytes.
21pub const UDP_HEADER_SIZE: u16 = 8;
22/// TCP header size in bytes, no options.
23pub const TCP_HEADER_SIZE: u16 = 20;
24
25/// An IP-layer packet. UDS lives outside this model — Unix sockets
26/// bypass the network stack and deliver socket-to-socket.
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub struct Packet {
29 pub src: IpAddr,
30 pub dst: IpAddr,
31 pub ttl: u8,
32 pub payload: Transport,
33}
34
35impl Packet {
36 /// Total size in bytes if this packet were actually serialized —
37 /// IP header + transport header + payload. Used to enforce MTU.
38 pub fn size(&self) -> u32 {
39 let ip_hdr = match self.dst {
40 IpAddr::V4(_) => IPV4_HEADER_SIZE,
41 IpAddr::V6(_) => IPV6_HEADER_SIZE,
42 } as u32;
43 ip_hdr + self.payload.size()
44 }
45}
46
47/// Transport-layer payload of a [`Packet`].
48#[derive(Debug, Clone, PartialEq, Eq)]
49pub enum Transport {
50 Udp(UdpDatagram),
51 Tcp(TcpSegment),
52}
53
54impl Transport {
55 /// Transport header + payload size.
56 pub fn size(&self) -> u32 {
57 match self {
58 Transport::Udp(d) => UDP_HEADER_SIZE as u32 + d.payload.len() as u32,
59 Transport::Tcp(s) => TCP_HEADER_SIZE as u32 + s.payload.len() as u32,
60 }
61 }
62}
63
64/// UDP datagram — `(src_port, dst_port, payload)`. Addresses live on the
65/// enclosing [`Packet`].
66#[derive(Debug, Clone, PartialEq, Eq)]
67pub struct UdpDatagram {
68 pub src_port: u16,
69 pub dst_port: u16,
70 pub payload: Bytes,
71}
72
73/// TCP segment. Fields mirror what a real kernel needs for state-machine
74/// decisions; anything not listed here (urgent pointer, options beyond
75/// MSS, checksum) is intentionally omitted.
76#[derive(Debug, Clone, PartialEq, Eq)]
77pub struct TcpSegment {
78 pub src_port: u16,
79 pub dst_port: u16,
80 pub seq: u32,
81 pub ack: u32,
82 pub flags: TcpFlags,
83 pub window: u16,
84 pub payload: Bytes,
85}
86
87/// TCP control flags.
88#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
89pub struct TcpFlags {
90 pub syn: bool,
91 pub ack: bool,
92 pub fin: bool,
93 pub rst: bool,
94 pub psh: bool,
95 pub urg: bool,
96}