netstack3_ip/
local_delivery.rs1use core::num::NonZeroU16;
8
9use net_types::SpecifiedAddr;
10use net_types::ip::{GenericOverIp, Ip, Ipv4, Ipv6};
11use netstack3_base::{IpExt, Marks};
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, Ipv6ExtensionHeaderData};
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
39#[derive(Debug, Clone)]
44pub struct LocalDeliveryPacketInfo<I: IpExt, H: IpHeaderInfo<I>> {
45 pub meta: ReceiveIpPacketMeta<I>,
47 pub header_info: H,
49 pub marks: Marks,
51}
52
53pub trait IpHeaderInfo<I> {
67 fn dscp_and_ecn(&self) -> DscpAndEcn;
69
70 fn hop_limit(&self) -> u8;
72
73 fn router_alert(&self) -> bool;
76
77 fn as_bytes(&self) -> [&[u8]; 2];
79}
80
81pub(crate) struct Ipv4HeaderInfo<'a> {
82 pub(crate) prefix: &'a packet_formats::ipv4::HeaderPrefix,
83 pub(crate) options: packet_formats::ipv4::Options<&'a [u8]>,
84}
85
86impl IpHeaderInfo<Ipv4> for Ipv4HeaderInfo<'_> {
87 fn dscp_and_ecn(&self) -> DscpAndEcn {
88 self.prefix.dscp_and_ecn()
89 }
90
91 fn hop_limit(&self) -> u8 {
92 self.prefix.ttl()
93 }
94
95 fn router_alert(&self) -> bool {
96 self.options.iter().any(|opt| matches!(opt, Ipv4Option::RouterAlert { .. }))
97 }
98
99 fn as_bytes(&self) -> [&[u8]; 2] {
100 use zerocopy::IntoBytes as _;
101 let Self { prefix, options } = self;
102 [prefix.as_bytes(), options.bytes()]
103 }
104}
105
106pub(crate) struct Ipv6HeaderInfo<'a> {
107 pub(crate) fixed: &'a packet_formats::ipv6::FixedHeader,
108 pub(crate) extension: packet_formats::ipv6::ExtensionHeaders<'a>,
109}
110
111impl IpHeaderInfo<Ipv6> for Ipv6HeaderInfo<'_> {
112 fn dscp_and_ecn(&self) -> DscpAndEcn {
113 self.fixed.dscp_and_ecn()
114 }
115
116 fn hop_limit(&self) -> u8 {
117 self.fixed.hop_limit()
118 }
119
120 fn router_alert(&self) -> bool {
121 self.extension.iter().any(|h| match h.data() {
122 Ipv6ExtensionHeaderData::HopByHopOptions { options } => {
123 options.iter().any(|h| matches!(h.data, HopByHopOptionData::RouterAlert { .. }))
124 }
125 _ => false,
126 })
127 }
128
129 fn as_bytes(&self) -> [&[u8]; 2] {
130 use zerocopy::IntoBytes as _;
131 let Self { fixed, extension } = self;
132 [fixed.as_bytes(), extension.bytes()]
133 }
134}
135
136#[cfg(any(test, feature = "testutils"))]
137pub(crate) mod testutil {
138 use super::*;
139 use alloc::vec::Vec;
140
141 impl<I: IpExt> Default for ReceiveIpPacketMeta<I> {
144 fn default() -> Self {
145 Self { broadcast: None, transparent_override: None }
146 }
147 }
148
149 impl<I: IpExt> Default for LocalDeliveryPacketInfo<I, FakeIpHeaderInfo> {
150 fn default() -> Self {
151 Self {
152 meta: Default::default(),
153 header_info: Default::default(),
154 marks: Default::default(),
155 }
156 }
157 }
158
159 #[derive(Debug, Default, Clone)]
161 pub struct FakeIpHeaderInfo {
162 pub dscp_and_ecn: DscpAndEcn,
164 pub hop_limit: u8,
166 pub router_alert: bool,
168 pub as_bytes: [Vec<u8>; 2],
170 }
171
172 impl<I: IpExt> IpHeaderInfo<I> for FakeIpHeaderInfo {
173 fn dscp_and_ecn(&self) -> DscpAndEcn {
174 self.dscp_and_ecn
175 }
176
177 fn hop_limit(&self) -> u8 {
178 self.hop_limit
179 }
180
181 fn router_alert(&self) -> bool {
182 self.router_alert
183 }
184
185 fn as_bytes(&self) -> [&[u8]; 2] {
186 [&self.as_bytes[0], &self.as_bytes[1]]
187 }
188 }
189}