netstack3_ip/
local_delivery.rs1use core::num::NonZeroU16;
8
9use net_types::SpecifiedAddr;
10use net_types::ip::{GenericOverIp, Ip, Ipv4, Ipv6};
11use netstack3_base::{GsoInfo, IpExt, Marks, NetworkParsingContext, PacketType};
12use packet_formats::ip::DscpAndEcn;
13use packet_formats::ipv4::Ipv4Header as _;
14use packet_formats::ipv4::options::Ipv4Option;
15use packet_formats::ipv6::Ipv6Header as _;
16use packet_formats::ipv6::ext_hdrs::{HopByHopOptionData, Ipv6ExtensionHeader};
17
18#[derive(Debug, GenericOverIp, Clone)]
20#[generic_over_ip(I, Ip)]
21pub struct TransparentLocalDelivery<I: IpExt> {
22 pub addr: SpecifiedAddr<I::Addr>,
24 pub port: NonZeroU16,
26}
27
28#[derive(Debug, GenericOverIp, Clone)]
30#[generic_over_ip(I, Ip)]
31pub struct ReceiveIpPacketMeta<I: IpExt> {
32 pub broadcast: Option<I::BroadcastMarker>,
34
35 pub transparent_override: Option<TransparentLocalDelivery<I>>,
37
38 pub parsing_context: NetworkParsingContext,
40}
41
42#[derive(Debug, Clone)]
47pub struct LocalDeliveryPacketInfo<I: IpExt, H: IpHeaderInfo<I>> {
48 pub meta: ReceiveIpPacketMeta<I>,
50 pub header_info: H,
52 pub marks: Marks,
54 pub packet_type: PacketType,
56 pub gso_info: Option<GsoInfo>,
58}
59
60pub trait IpHeaderInfo<I> {
74 fn dscp_and_ecn(&self) -> DscpAndEcn;
76
77 fn hop_limit(&self) -> u8;
79
80 fn router_alert(&self) -> bool;
83
84 fn as_bytes(&self) -> [&[u8]; 2];
86}
87
88pub(crate) struct Ipv4HeaderInfo<'a> {
89 pub(crate) prefix: &'a packet_formats::ipv4::HeaderPrefix,
90 pub(crate) options: packet_formats::ipv4::Options<&'a [u8]>,
91}
92
93impl IpHeaderInfo<Ipv4> for Ipv4HeaderInfo<'_> {
94 fn dscp_and_ecn(&self) -> DscpAndEcn {
95 self.prefix.dscp_and_ecn()
96 }
97
98 fn hop_limit(&self) -> u8 {
99 self.prefix.ttl()
100 }
101
102 fn router_alert(&self) -> bool {
103 self.options.iter().any(|opt| matches!(opt, Ipv4Option::RouterAlert { .. }))
104 }
105
106 fn as_bytes(&self) -> [&[u8]; 2] {
107 use zerocopy::IntoBytes as _;
108 let Self { prefix, options } = self;
109 [prefix.as_bytes(), options.bytes()]
110 }
111}
112
113pub(crate) struct Ipv6HeaderInfo<'a> {
114 pub(crate) fixed: &'a packet_formats::ipv6::FixedHeader,
115 pub(crate) extension: packet_formats::ipv6::ExtensionHeaders<'a>,
116}
117
118impl IpHeaderInfo<Ipv6> for Ipv6HeaderInfo<'_> {
119 fn dscp_and_ecn(&self) -> DscpAndEcn {
120 self.fixed.dscp_and_ecn()
121 }
122
123 fn hop_limit(&self) -> u8 {
124 self.fixed.hop_limit()
125 }
126
127 fn router_alert(&self) -> bool {
128 self.extension.iter().any(|h| match h {
129 Ipv6ExtensionHeader::HopByHopOptions { options } => {
130 options.iter().any(|h| matches!(h.data, HopByHopOptionData::RouterAlert { .. }))
131 }
132 _ => false,
133 })
134 }
135
136 fn as_bytes(&self) -> [&[u8]; 2] {
137 use zerocopy::IntoBytes as _;
138 let Self { fixed, extension } = self;
139 [fixed.as_bytes(), extension.bytes()]
140 }
141}
142
143#[cfg(any(test, feature = "testutils"))]
144pub(crate) mod testutil {
145 use super::*;
146 use alloc::vec::Vec;
147
148 impl<I: IpExt> Default for ReceiveIpPacketMeta<I> {
151 fn default() -> Self {
152 Self {
153 broadcast: None,
154 transparent_override: None,
155 parsing_context: NetworkParsingContext::default(),
156 }
157 }
158 }
159
160 impl<I: IpExt> Default for LocalDeliveryPacketInfo<I, FakeIpHeaderInfo> {
161 fn default() -> Self {
162 Self {
163 meta: Default::default(),
164 header_info: Default::default(),
165 marks: Default::default(),
166 packet_type: PacketType::Host,
167 gso_info: None,
168 }
169 }
170 }
171
172 #[derive(Debug, Default, Clone)]
174 pub struct FakeIpHeaderInfo {
175 pub dscp_and_ecn: DscpAndEcn,
177 pub hop_limit: u8,
179 pub router_alert: bool,
181 pub as_bytes: [Vec<u8>; 2],
183 }
184
185 impl<I: IpExt> IpHeaderInfo<I> for FakeIpHeaderInfo {
186 fn dscp_and_ecn(&self) -> DscpAndEcn {
187 self.dscp_and_ecn
188 }
189
190 fn hop_limit(&self) -> u8 {
191 self.hop_limit
192 }
193
194 fn router_alert(&self) -> bool {
195 self.router_alert
196 }
197
198 fn as_bytes(&self) -> [&[u8]; 2] {
199 [&self.as_bytes[0], &self.as_bytes[1]]
200 }
201 }
202}