1mod integration;
59
60use derivative::Derivative;
61use net_types::ip::{Ip, Ipv4, Ipv6};
62use netstack3_base::socket::SocketCookie;
63use netstack3_base::{CoreTxMetadataContext, HandleableTimer, TimerHandler, TxMetadata};
64use netstack3_datagram as datagram;
65use netstack3_device::WeakDeviceId;
66use netstack3_icmp_echo::{IcmpSocketTxMetadata, IcmpSockets};
67use netstack3_tcp::{
68 self as tcp, TcpCountersWithSocket, TcpCountersWithoutSocket, TcpSocketTxMetadata, TcpState,
69 TcpTimerId,
70};
71use netstack3_udp::{
72 UdpCountersWithSocket, UdpCountersWithoutSocket, UdpSocketTxMetadata, UdpState,
73};
74
75use crate::{BindingsContext, BindingsTypes, CoreCtx, IpExt};
76
77#[derive(Default, Clone)]
79pub struct TransportStateBuilder;
80
81impl TransportStateBuilder {
82 pub(crate) fn build_with_ctx<BC: BindingsContext>(
83 self,
84 bindings_ctx: &mut BC,
85 ) -> TransportLayerState<BC> {
86 let now = bindings_ctx.now();
87 let mut rng = bindings_ctx.rng();
88 TransportLayerState {
89 udpv4: Default::default(),
90 udpv6: Default::default(),
91 tcpv4: TcpState::new(now, &mut rng),
92 tcpv6: TcpState::new(now, &mut rng),
93 icmp_echo_v4: Default::default(),
94 icmp_echo_v6: Default::default(),
95 }
96 }
97}
98
99pub struct TransportLayerState<BT: BindingsTypes> {
101 udpv4: UdpState<Ipv4, WeakDeviceId<BT>, BT>,
102 udpv6: UdpState<Ipv6, WeakDeviceId<BT>, BT>,
103 tcpv4: TcpState<Ipv4, WeakDeviceId<BT>, BT>,
104 tcpv6: TcpState<Ipv6, WeakDeviceId<BT>, BT>,
105 icmp_echo_v4: IcmpSockets<Ipv4, WeakDeviceId<BT>, BT>,
106 icmp_echo_v6: IcmpSockets<Ipv6, WeakDeviceId<BT>, BT>,
107}
108
109impl<BT: BindingsTypes> TransportLayerState<BT> {
110 fn tcp_state<I: tcp::DualStackIpExt>(&self) -> &TcpState<I, WeakDeviceId<BT>, BT> {
111 I::map_ip((), |()| &self.tcpv4, |()| &self.tcpv6)
112 }
113
114 fn udp_state<I: datagram::IpExt>(&self) -> &UdpState<I, WeakDeviceId<BT>, BT> {
115 I::map_ip((), |()| &self.udpv4, |()| &self.udpv6)
116 }
117
118 pub(crate) fn icmp_echo_state<I: datagram::IpExt>(
119 &self,
120 ) -> &IcmpSockets<I, WeakDeviceId<BT>, BT> {
121 I::map_ip((), |()| &self.icmp_echo_v4, |()| &self.icmp_echo_v6)
122 }
123
124 pub(crate) fn udp_counters_with_socket<I: Ip>(&self) -> &UdpCountersWithSocket<I> {
125 I::map_ip((), |()| &self.udpv4.counters_with_socket, |()| &self.udpv6.counters_with_socket)
126 }
127
128 pub(crate) fn udp_counters_without_socket<I: Ip>(&self) -> &UdpCountersWithoutSocket<I> {
129 I::map_ip(
130 (),
131 |()| &self.udpv4.counters_without_socket,
132 |()| &self.udpv6.counters_without_socket,
133 )
134 }
135
136 pub(crate) fn tcp_counters_with_socket<I: Ip>(&self) -> &TcpCountersWithSocket<I> {
137 I::map_ip((), |()| &self.tcpv4.counters_with_socket, |()| &self.tcpv6.counters_with_socket)
138 }
139
140 pub(crate) fn tcp_counters_without_socket<I: Ip>(&self) -> &TcpCountersWithoutSocket<I> {
141 I::map_ip(
142 (),
143 |()| &self.tcpv4.counters_without_socket,
144 |()| &self.tcpv6.counters_without_socket,
145 )
146 }
147}
148
149#[derive(Derivative)]
151#[derivative(
152 Clone(bound = ""),
153 Eq(bound = ""),
154 PartialEq(bound = ""),
155 Hash(bound = ""),
156 Debug(bound = "")
157)]
158pub(crate) enum TransportLayerTimerId<BT: BindingsTypes> {
159 Tcp(TcpTimerId<WeakDeviceId<BT>, BT>),
160}
161
162impl<CC, BT> HandleableTimer<CC, BT> for TransportLayerTimerId<BT>
163where
164 BT: BindingsTypes,
165 CC: TimerHandler<BT, TcpTimerId<WeakDeviceId<BT>, BT>>,
166{
167 fn handle(self, core_ctx: &mut CC, bindings_ctx: &mut BT, timer: BT::UniqueTimerId) {
168 match self {
169 TransportLayerTimerId::Tcp(id) => core_ctx.handle_timer(bindings_ctx, id, timer),
170 }
171 }
172}
173
174impl<BT: BindingsTypes> From<TcpTimerId<WeakDeviceId<BT>, BT>> for TransportLayerTimerId<BT> {
175 fn from(id: TcpTimerId<WeakDeviceId<BT>, BT>) -> Self {
176 TransportLayerTimerId::Tcp(id)
177 }
178}
179
180#[derive(Derivative)]
182#[derivative(Debug = "transparent", Debug(bound = ""), Default(bound = ""))]
183#[cfg_attr(any(test, feature = "testutils"), derivative(PartialEq(bound = "")))]
184pub struct CoreTxMetadata<BT: BindingsTypes>(TxMetadataInner<BT>);
185
186#[derive(Derivative)]
190#[derivative(Debug(bound = ""), Default(bound = ""))]
191#[cfg_attr(any(test, feature = "testutils"), derivative(PartialEq(bound = "")))]
192enum TxMetadataInner<BT: BindingsTypes> {
193 #[derivative(Default)]
194 None,
195 #[derivative(Debug = "transparent")]
196 Udpv4(UdpSocketTxMetadata<Ipv4, WeakDeviceId<BT>, BT>),
197 #[derivative(Debug = "transparent")]
198 Udpv6(UdpSocketTxMetadata<Ipv6, WeakDeviceId<BT>, BT>),
199 #[derivative(Debug = "transparent")]
200 Icmpv4(IcmpSocketTxMetadata<Ipv4, WeakDeviceId<BT>, BT>),
201 #[derivative(Debug = "transparent")]
202 Icmpv6(IcmpSocketTxMetadata<Ipv6, WeakDeviceId<BT>, BT>),
203 #[derivative(Debug = "transparent")]
204 Tcpv4(TcpSocketTxMetadata<Ipv4, WeakDeviceId<BT>, BT>),
205 #[derivative(Debug = "transparent")]
206 Tcpv6(TcpSocketTxMetadata<Ipv6, WeakDeviceId<BT>, BT>),
207}
208
209impl<I: IpExt, L, BT: BindingsTypes>
210 CoreTxMetadataContext<UdpSocketTxMetadata<I, WeakDeviceId<BT>, BT>, BT> for CoreCtx<'_, BT, L>
211{
212 fn convert_tx_meta(
213 &self,
214 tx_meta: UdpSocketTxMetadata<I, WeakDeviceId<BT>, BT>,
215 ) -> CoreTxMetadata<BT> {
216 CoreTxMetadata(I::map_ip_in(tx_meta, TxMetadataInner::Udpv4, TxMetadataInner::Udpv6))
217 }
218}
219
220impl<I: IpExt, L, BT: BindingsTypes>
221 CoreTxMetadataContext<IcmpSocketTxMetadata<I, WeakDeviceId<BT>, BT>, BT>
222 for CoreCtx<'_, BT, L>
223{
224 fn convert_tx_meta(
225 &self,
226 tx_meta: IcmpSocketTxMetadata<I, WeakDeviceId<BT>, BT>,
227 ) -> CoreTxMetadata<BT> {
228 CoreTxMetadata(I::map_ip_in(tx_meta, TxMetadataInner::Icmpv4, TxMetadataInner::Icmpv6))
229 }
230}
231
232impl<I: IpExt, L, BT: BindingsTypes>
233 CoreTxMetadataContext<TcpSocketTxMetadata<I, WeakDeviceId<BT>, BT>, BT> for CoreCtx<'_, BT, L>
234{
235 fn convert_tx_meta(
236 &self,
237 tx_meta: TcpSocketTxMetadata<I, WeakDeviceId<BT>, BT>,
238 ) -> CoreTxMetadata<BT> {
239 CoreTxMetadata(I::map_ip_in(tx_meta, TxMetadataInner::Tcpv4, TxMetadataInner::Tcpv6))
240 }
241}
242
243impl<BT: BindingsTypes> TxMetadata for CoreTxMetadata<BT> {
244 fn socket_cookie(&self) -> Option<SocketCookie> {
245 let CoreTxMetadata(inner) = self;
246 match inner {
247 TxMetadataInner::None => None,
249 TxMetadataInner::Tcpv4(tx_metadata) => {
250 tx_metadata.socket().upgrade().map(|s| s.socket_cookie())
251 }
252 TxMetadataInner::Tcpv6(tx_metadata) => {
253 tx_metadata.socket().upgrade().map(|s| s.socket_cookie())
254 }
255 TxMetadataInner::Udpv4(tx_metadata) => {
256 tx_metadata.socket().upgrade().map(|s| s.socket_cookie())
257 }
258 TxMetadataInner::Udpv6(tx_metadata) => {
259 tx_metadata.socket().upgrade().map(|s| s.socket_cookie())
260 }
261 TxMetadataInner::Icmpv4(tx_metadata) => {
262 tx_metadata.socket().upgrade().map(|s| s.socket_cookie())
263 }
264 TxMetadataInner::Icmpv6(tx_metadata) => {
265 tx_metadata.socket().upgrade().map(|s| s.socket_cookie())
266 }
267 }
268 }
269}