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, TcpState, TcpTimerId,
68};
69use netstack3_udp::{UdpCounters, UdpSocketTxMetadata, UdpState, UdpStateBuilder};
70
71use crate::{BindingsContext, BindingsTypes, CoreCtx, IpExt};
72
73#[derive(Default, Clone)]
75pub struct TransportStateBuilder {
76 udp: UdpStateBuilder,
77}
78
79impl TransportStateBuilder {
80 pub fn udp_builder(&mut self) -> &mut UdpStateBuilder {
82 &mut self.udp
83 }
84
85 pub(crate) fn build_with_ctx<BC: BindingsContext>(
86 self,
87 bindings_ctx: &mut BC,
88 ) -> TransportLayerState<BC> {
89 let now = bindings_ctx.now();
90 let mut rng = bindings_ctx.rng();
91 TransportLayerState {
92 udpv4: self.udp.clone().build(),
93 udpv6: self.udp.build(),
94 tcpv4: TcpState::new(now, &mut rng),
95 tcpv6: TcpState::new(now, &mut rng),
96 icmp_echo_v4: Default::default(),
97 icmp_echo_v6: Default::default(),
98 }
99 }
100}
101
102pub struct TransportLayerState<BT: BindingsTypes> {
104 udpv4: UdpState<Ipv4, WeakDeviceId<BT>, BT>,
105 udpv6: UdpState<Ipv6, WeakDeviceId<BT>, BT>,
106 tcpv4: TcpState<Ipv4, WeakDeviceId<BT>, BT>,
107 tcpv6: TcpState<Ipv6, WeakDeviceId<BT>, BT>,
108 icmp_echo_v4: IcmpSockets<Ipv4, WeakDeviceId<BT>, BT>,
109 icmp_echo_v6: IcmpSockets<Ipv6, WeakDeviceId<BT>, BT>,
110}
111
112impl<BT: BindingsTypes> TransportLayerState<BT> {
113 fn tcp_state<I: tcp::DualStackIpExt>(&self) -> &TcpState<I, WeakDeviceId<BT>, BT> {
114 I::map_ip((), |()| &self.tcpv4, |()| &self.tcpv6)
115 }
116
117 fn udp_state<I: datagram::IpExt>(&self) -> &UdpState<I, WeakDeviceId<BT>, BT> {
118 I::map_ip((), |()| &self.udpv4, |()| &self.udpv6)
119 }
120
121 pub(crate) fn icmp_echo_state<I: datagram::IpExt>(
122 &self,
123 ) -> &IcmpSockets<I, WeakDeviceId<BT>, BT> {
124 I::map_ip((), |()| &self.icmp_echo_v4, |()| &self.icmp_echo_v6)
125 }
126
127 pub(crate) fn udp_counters<I: Ip>(&self) -> &UdpCounters<I> {
128 I::map_ip((), |()| &self.udpv4.counters, |()| &self.udpv6.counters)
129 }
130
131 pub(crate) fn tcp_counters_with_socket<I: Ip>(&self) -> &TcpCountersWithSocket<I> {
132 I::map_ip((), |()| &self.tcpv4.counters_with_socket, |()| &self.tcpv6.counters_with_socket)
133 }
134
135 pub(crate) fn tcp_counters_without_socket<I: Ip>(&self) -> &TcpCountersWithoutSocket<I> {
136 I::map_ip(
137 (),
138 |()| &self.tcpv4.counters_without_socket,
139 |()| &self.tcpv6.counters_without_socket,
140 )
141 }
142}
143
144#[derive(Derivative)]
146#[derivative(
147 Clone(bound = ""),
148 Eq(bound = ""),
149 PartialEq(bound = ""),
150 Hash(bound = ""),
151 Debug(bound = "")
152)]
153pub(crate) enum TransportLayerTimerId<BT: BindingsTypes> {
154 Tcp(TcpTimerId<WeakDeviceId<BT>, BT>),
155}
156
157impl<CC, BT> HandleableTimer<CC, BT> for TransportLayerTimerId<BT>
158where
159 BT: BindingsTypes,
160 CC: TimerHandler<BT, TcpTimerId<WeakDeviceId<BT>, BT>>,
161{
162 fn handle(self, core_ctx: &mut CC, bindings_ctx: &mut BT, timer: BT::UniqueTimerId) {
163 match self {
164 TransportLayerTimerId::Tcp(id) => core_ctx.handle_timer(bindings_ctx, id, timer),
165 }
166 }
167}
168
169impl<BT: BindingsTypes> From<TcpTimerId<WeakDeviceId<BT>, BT>> for TransportLayerTimerId<BT> {
170 fn from(id: TcpTimerId<WeakDeviceId<BT>, BT>) -> Self {
171 TransportLayerTimerId::Tcp(id)
172 }
173}
174
175#[derive(Derivative)]
177#[derivative(Debug = "transparent", Debug(bound = ""), Default(bound = ""))]
178#[cfg_attr(any(test, feature = "testutils"), derivative(PartialEq(bound = "")))]
179pub struct TxMetadata<BT: BindingsTypes>(TxMetadataInner<BT>);
180
181#[derive(Derivative)]
185#[derivative(Debug(bound = ""), Default(bound = ""))]
186#[cfg_attr(any(test, feature = "testutils"), derivative(PartialEq(bound = "")))]
187enum TxMetadataInner<BT: BindingsTypes> {
188 #[derivative(Default)]
189 None,
190 #[derivative(Debug = "transparent")]
191 Udpv4(UdpSocketTxMetadata<Ipv4, WeakDeviceId<BT>, BT>),
192 #[derivative(Debug = "transparent")]
193 Udpv6(UdpSocketTxMetadata<Ipv6, WeakDeviceId<BT>, BT>),
194 #[derivative(Debug = "transparent")]
195 Icmpv4(IcmpSocketTxMetadata<Ipv4, WeakDeviceId<BT>, BT>),
196 #[derivative(Debug = "transparent")]
197 Icmpv6(IcmpSocketTxMetadata<Ipv6, WeakDeviceId<BT>, BT>),
198}
199
200impl<I: IpExt, L, BT: BindingsTypes>
201 CoreTxMetadataContext<UdpSocketTxMetadata<I, WeakDeviceId<BT>, BT>, BT> for CoreCtx<'_, BT, L>
202{
203 fn convert_tx_meta(
204 &self,
205 tx_meta: UdpSocketTxMetadata<I, WeakDeviceId<BT>, BT>,
206 ) -> TxMetadata<BT> {
207 TxMetadata(I::map_ip_in(tx_meta, TxMetadataInner::Udpv4, TxMetadataInner::Udpv6))
208 }
209}
210
211impl<I: IpExt, L, BT: BindingsTypes>
212 CoreTxMetadataContext<IcmpSocketTxMetadata<I, WeakDeviceId<BT>, BT>, BT>
213 for CoreCtx<'_, BT, L>
214{
215 fn convert_tx_meta(
216 &self,
217 tx_meta: IcmpSocketTxMetadata<I, WeakDeviceId<BT>, BT>,
218 ) -> TxMetadata<BT> {
219 TxMetadata(I::map_ip_in(tx_meta, TxMetadataInner::Icmpv4, TxMetadataInner::Icmpv6))
220 }
221}