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