netstack3_ip/
local_delivery.rs1use core::num::NonZeroU16;
8
9use net_types::ip::{GenericOverIp, Ip, Ipv4, Ipv6};
10use net_types::SpecifiedAddr;
11use netstack3_base::{IpExt, Marks};
12use packet_formats::ip::DscpAndEcn;
13use packet_formats::ipv4::options::Ipv4Option;
14use packet_formats::ipv4::Ipv4Header as _;
15use packet_formats::ipv6::ext_hdrs::{HopByHopOptionData, Ipv6ExtensionHeaderData};
16use packet_formats::ipv6::Ipv6Header as _;
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
78pub(crate) struct Ipv4HeaderInfo<'a> {
79 pub(crate) prefix: &'a packet_formats::ipv4::HeaderPrefix,
80 pub(crate) options: packet_formats::ipv4::Options<&'a [u8]>,
81}
82
83impl IpHeaderInfo<Ipv4> for Ipv4HeaderInfo<'_> {
84 fn dscp_and_ecn(&self) -> DscpAndEcn {
85 self.prefix.dscp_and_ecn()
86 }
87
88 fn hop_limit(&self) -> u8 {
89 self.prefix.ttl()
90 }
91
92 fn router_alert(&self) -> bool {
93 self.options.iter().any(|opt| matches!(opt, Ipv4Option::RouterAlert { .. }))
94 }
95}
96
97pub(crate) struct Ipv6HeaderInfo<'a> {
98 pub(crate) fixed: &'a packet_formats::ipv6::FixedHeader,
99 pub(crate) extension: packet_formats::ipv6::ExtensionHeaders<'a>,
100}
101
102impl IpHeaderInfo<Ipv6> for Ipv6HeaderInfo<'_> {
103 fn dscp_and_ecn(&self) -> DscpAndEcn {
104 self.fixed.dscp_and_ecn()
105 }
106
107 fn hop_limit(&self) -> u8 {
108 self.fixed.hop_limit()
109 }
110
111 fn router_alert(&self) -> bool {
112 self.extension.iter().any(|h| match h.data() {
113 Ipv6ExtensionHeaderData::HopByHopOptions { options } => {
114 options.iter().any(|h| matches!(h.data, HopByHopOptionData::RouterAlert { .. }))
115 }
116 _ => false,
117 })
118 }
119}
120
121#[cfg(any(test, feature = "testutils"))]
122pub(crate) mod testutil {
123 use super::*;
124
125 impl<I: IpExt> Default for ReceiveIpPacketMeta<I> {
128 fn default() -> Self {
129 Self { broadcast: None, transparent_override: None }
130 }
131 }
132
133 impl<I: IpExt> Default for LocalDeliveryPacketInfo<I, FakeIpHeaderInfo> {
134 fn default() -> Self {
135 Self {
136 meta: Default::default(),
137 header_info: Default::default(),
138 marks: Default::default(),
139 }
140 }
141 }
142
143 #[derive(Debug, Default)]
145 pub struct FakeIpHeaderInfo {
146 pub dscp_and_ecn: DscpAndEcn,
148 pub hop_limit: u8,
150 pub router_alert: bool,
152 }
153
154 impl<I: IpExt> IpHeaderInfo<I> for FakeIpHeaderInfo {
155 fn dscp_and_ecn(&self) -> DscpAndEcn {
156 self.dscp_and_ecn
157 }
158
159 fn hop_limit(&self) -> u8 {
160 self.hop_limit
161 }
162
163 fn router_alert(&self) -> bool {
164 self.router_alert
165 }
166 }
167}