twizzler_net/
client.rs

1use std::net::IpAddr;
2
3use monitor_api::CompartmentHandle;
4use secgate::{
5    TwzError,
6    util::{Descriptor, Handle},
7};
8use smoltcp::{
9    phy::{DeviceCapabilities, Medium, RxToken, TxToken},
10    wire::EthernetAddress,
11};
12use twizzler::object::{MapFlags, ObjID, Object, RawObject};
13use twizzler_abi::syscall::ThreadSyncSleep;
14use twizzler_io::packet::PacketObject;
15use twizzler_queue::{Queue, QueueBase};
16
17use crate::{
18    ClientMsg, ClientMsgKind, ClientRet, INVALID_PACKET, PacketNum, PacketSet, ServerMsg,
19    ServerMsgKind, ServerRet, endpoint::Pair,
20};
21
22pub struct NetClient {
23    tx: Pair<ClientMsg, ServerRet>,
24    rx: Pair<ServerMsg, ClientRet>,
25    handle: Descriptor,
26    pending_rx: PacketSet,
27    pending_id: Option<u32>,
28    pub info: NetClientOpenInfo,
29}
30
31#[derive(Clone, Copy, Debug)]
32#[repr(C)]
33pub struct NetClientOpenInfo {
34    pub tx_buf: ObjID,
35    pub rx_buf: ObjID,
36    pub tx_queue: ObjID,
37    pub rx_queue: ObjID,
38    pub handle: Descriptor,
39    pub addr: IpAddr,
40    pub addr_prefix_len: u8,
41    pub gateway: IpAddr,
42    pub hwaddr: EthernetAddress,
43}
44
45impl NetClient {
46    pub fn rx_waiter(&self) -> ThreadSyncSleep {
47        self.rx.rx_waiter()
48    }
49
50    pub fn has_rx_pending(&self) -> bool {
51        self.rx.has_pending_msg() || self.pending_rx.0.iter().any(|p| *p != INVALID_PACKET)
52    }
53}
54
55pub fn net_open_client(config: NetClientConfig) -> Result<NetClientOpenInfo, TwzError> {
56    let comp = CompartmentHandle::lookup("net")?;
57    let gate = unsafe { comp.dynamic_gate("twz_net_open_client") }?;
58    (gate)(config)
59}
60
61pub fn net_drop_client(desc: u32) -> Result<(), TwzError> {
62    let comp = CompartmentHandle::lookup("net")?;
63    let gate = unsafe { comp.dynamic_gate("twz_net_drop_client") }?;
64    (gate)(desc)
65}
66
67pub fn net_alloc_port(desc: Descriptor, port: Option<u16>) -> Result<u16, TwzError> {
68    let comp = CompartmentHandle::lookup("net")?;
69    let gate = unsafe { comp.dynamic_gate("twz_net_alloc_port") }?;
70    (gate)(desc, port)
71}
72
73pub fn net_release_port(desc: Descriptor, port: u16) -> Result<(), TwzError> {
74    let comp = CompartmentHandle::lookup("net")?;
75    let gate = unsafe { comp.dynamic_gate("twz_net_release_port") }?;
76    (gate)(desc, port)
77}
78
79impl secgate::util::Handle for NetClient {
80    type OpenError = TwzError;
81
82    type OpenInfo = NetClientConfig;
83
84    fn open(info: Self::OpenInfo) -> Result<Self, Self::OpenError>
85    where
86        Self: Sized,
87    {
88        let info = net_open_client(info)?;
89        let tx_queue = Object::<QueueBase<ClientMsg, ServerRet>>::map(
90            info.tx_queue,
91            MapFlags::READ | MapFlags::WRITE,
92        )?;
93        let rx_queue = Object::<QueueBase<ServerMsg, ClientRet>>::map(
94            info.rx_queue,
95            MapFlags::READ | MapFlags::WRITE,
96        )?;
97        let tx = Pair::new(
98            PacketObject::from(Object::map(info.tx_buf, MapFlags::READ | MapFlags::WRITE)?),
99            Queue::from(tx_queue.handle().clone()),
100        );
101        let rx = Pair::new(
102            PacketObject::from(Object::map(info.rx_buf, MapFlags::READ | MapFlags::WRITE)?),
103            Queue::from(rx_queue.handle().clone()),
104        );
105        Ok(Self {
106            tx,
107            rx,
108            handle: info.handle,
109            pending_id: None,
110            pending_rx: PacketSet::new(),
111            info,
112        })
113    }
114
115    fn release(&mut self) {
116        let _ = net_drop_client(self.handle);
117    }
118}
119
120impl Drop for NetClient {
121    fn drop(&mut self) {
122        self.release();
123    }
124}
125
126#[derive(Clone, Copy, Debug)]
127#[repr(C)]
128pub struct NetClientConfig {}
129
130impl smoltcp::phy::Device for NetClient {
131    type RxToken<'a>
132        = NetClientRxToken<'a>
133    where
134        Self: 'a;
135
136    type TxToken<'a>
137        = NetClientTxToken<'a>
138    where
139        Self: 'a;
140
141    fn receive(
142        &mut self,
143        timestamp: smoltcp::time::Instant,
144    ) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> {
145        let idx = self.pending_rx.0.iter().position(|x| *x != INVALID_PACKET);
146        if let Some(idx) = idx {
147            let next = self.pending_rx.0[idx];
148            self.pending_rx.0[idx] = INVALID_PACKET;
149            self.tx.check_completions();
150
151            return Some((
152                NetClientRxToken {
153                    nc: self,
154                    packet: next,
155                },
156                NetClientTxToken {
157                    nc: self,
158                    packet: self.tx.allocate_packet().unwrap(),
159                    consumed: false,
160                },
161            ));
162        }
163
164        if let Some(pending_id) = self.pending_id.take() {
165            self.rx.complete(pending_id, ClientRet {});
166        }
167
168        let (id, msg) = self.rx.recv_msg()?;
169        self.pending_id = Some(id);
170        match msg.kind {
171            ServerMsgKind::Tx(packet_set) => {
172                self.pending_rx = packet_set;
173            }
174        }
175        self.receive(timestamp)
176    }
177
178    fn transmit(&mut self, _timestamp: smoltcp::time::Instant) -> Option<Self::TxToken<'_>> {
179        self.tx.check_completions();
180        let packet = self.tx.allocate_packet()?;
181        Some(NetClientTxToken {
182            nc: self,
183            packet,
184            consumed: false,
185        })
186    }
187
188    fn capabilities(&self) -> DeviceCapabilities {
189        let mut cap = DeviceCapabilities::default();
190        cap.medium = Medium::Ethernet;
191        cap.max_transmission_unit = 1514;
192        cap.max_burst_size = Some(1);
193        cap
194    }
195}
196
197pub struct NetClientTxToken<'a> {
198    nc: &'a NetClient,
199    packet: PacketNum,
200    consumed: bool,
201}
202
203pub struct NetClientRxToken<'a> {
204    nc: &'a NetClient,
205    packet: PacketNum,
206}
207
208impl TxToken for NetClientTxToken<'_> {
209    fn consume<R, F>(mut self, len: usize, f: F) -> R
210    where
211        F: FnOnce(&mut [u8]) -> R,
212    {
213        if len > self.nc.tx.packet_size() {
214            panic!("packet size exceeded");
215        }
216        let mem = self.nc.tx.packet_mem_mut(self.packet);
217        let ret = f(&mut mem[0..len]);
218        self.consumed = true;
219
220        self.nc
221            .tx
222            .send_packets(&[self.packet], |s| ClientMsg {
223                kind: ClientMsgKind::Tx(s),
224            })
225            .expect("failed to send packet");
226
227        ret
228    }
229}
230
231impl RxToken for NetClientRxToken<'_> {
232    fn consume<R, F>(self, f: F) -> R
233    where
234        F: FnOnce(&mut [u8]) -> R,
235    {
236        let mem = self.nc.rx.packet_mem_mut(self.packet);
237        f(mem)
238    }
239}
240
241impl Drop for NetClientTxToken<'_> {
242    fn drop(&mut self) {
243        if !self.consumed {
244            self.nc.tx.release_packet(self.packet);
245        }
246    }
247}