1use crate::autonet::NetworkMetadata;
2use crate::chandev::ChannelDevice;
3use crate::nat::Nat;
4use crate::proxynat::ProxyNatHandlerFactory;
5use crate::raw_socket::{AsyncRawSocketChannel, RawSocketHandle, RawSocketProtocol};
6use crate::vbridge::{BridgeJoinHandle, VirtualBridge};
7use crate::EXTRA_MTU;
8use anyhow::{anyhow, Result};
9use bytes::BytesMut;
10use futures::TryStreamExt;
11use log::{info, trace, warn};
12use smoltcp::iface::{Config, Interface, SocketSet};
13use smoltcp::phy::Medium;
14use smoltcp::time::Instant;
15use smoltcp::wire::{HardwareAddress, IpCidr};
16use tokio::select;
17use tokio::sync::mpsc::{channel, Receiver};
18use tokio::task::JoinHandle;
19
20const TX_CHANNEL_BUFFER_LEN: usize = 3000;
21
22#[derive(Clone)]
23pub struct NetworkBackend {
24 metadata: NetworkMetadata,
25 bridge: VirtualBridge,
26}
27
28#[derive(Debug)]
29enum NetworkStackSelect {
30 Receive(Option<BytesMut>),
31 Send(Option<BytesMut>),
32}
33
34struct NetworkStack<'a> {
35 tx: Receiver<BytesMut>,
36 kdev: AsyncRawSocketChannel,
37 udev: ChannelDevice,
38 interface: Interface,
39 sockets: SocketSet<'a>,
40 nat: Nat,
41 bridge: BridgeJoinHandle,
42}
43
44impl NetworkStack<'_> {
45 async fn poll(&mut self) -> Result<bool> {
46 let what = select! {
47 biased;
48 x = self.kdev.receiver.recv() => NetworkStackSelect::Receive(x),
49 x = self.tx.recv() => NetworkStackSelect::Send(x),
50 x = self.bridge.from_bridge_receiver.recv() => NetworkStackSelect::Send(x),
51 x = self.bridge.from_broadcast_receiver.recv() => NetworkStackSelect::Send(x.ok()),
52 };
53
54 match what {
55 NetworkStackSelect::Receive(Some(packet)) => {
56 if let Err(error) = self.bridge.to_bridge_sender.try_send(packet.clone()) {
57 trace!("failed to send zone packet to bridge: {}", error);
58 }
59
60 if let Err(error) = self.nat.receive_sender.try_send(packet.clone()) {
61 trace!("failed to send zone packet to nat: {}", error);
62 }
63
64 self.udev.rx = Some(packet);
65 self.interface
66 .poll(Instant::now(), &mut self.udev, &mut self.sockets);
67 }
68
69 NetworkStackSelect::Send(Some(packet)) => {
70 if let Err(error) = self.kdev.sender.try_send(packet) {
71 warn!("failed to transmit packet to interface: {}", error);
72 }
73 }
74
75 NetworkStackSelect::Receive(None) | NetworkStackSelect::Send(None) => {
76 return Ok(false);
77 }
78 }
79
80 Ok(true)
81 }
82}
83
84impl NetworkBackend {
85 pub fn new(metadata: NetworkMetadata, bridge: VirtualBridge) -> Result<Self> {
86 Ok(Self { metadata, bridge })
87 }
88
89 pub async fn init(&mut self) -> Result<()> {
90 let interface = self.metadata.interface();
91 let (connection, handle, _) = rtnetlink::new_connection()?;
92 tokio::spawn(connection);
93
94 let mut links = handle.link().get().match_name(interface.clone()).execute();
95 let link = links.try_next().await?;
96 if link.is_none() {
97 return Err(anyhow!(
98 "unable to find network interface named {}",
99 interface
100 ));
101 }
102 let link = link.unwrap();
103 handle.link().set(link.header.index).up().execute().await?;
104 Ok(())
105 }
106
107 pub async fn run(&self) -> Result<()> {
108 let mut stack = self.create_network_stack().await?;
109 loop {
110 if !stack.poll().await? {
111 break;
112 }
113 }
114 Ok(())
115 }
116
117 async fn create_network_stack(&self) -> Result<NetworkStack> {
118 let interface = self.metadata.interface();
119 let proxy = Box::new(ProxyNatHandlerFactory::new());
120 let addresses: Vec<IpCidr> = vec![
121 self.metadata.gateway.ipv4.into(),
122 self.metadata.gateway.ipv6.into(),
123 ];
124 let mut kdev =
125 RawSocketHandle::bound_to_interface(&interface, RawSocketProtocol::Ethernet)?;
126 let mtu = kdev.mtu_of_interface(&interface)? + EXTRA_MTU;
127 let (tx_sender, tx_receiver) = channel::<BytesMut>(TX_CHANNEL_BUFFER_LEN);
128 let mut udev = ChannelDevice::new(mtu, Medium::Ethernet, tx_sender.clone());
129 let mac = self.metadata.gateway.mac;
130 let local_cidrs = addresses.clone();
131 let nat = Nat::new(mtu, proxy, mac, local_cidrs, tx_sender.clone())?;
132 let hardware_addr = HardwareAddress::Ethernet(mac);
133 let config = Config::new(hardware_addr);
134 let mut iface = Interface::new(config, &mut udev, Instant::now());
135 iface.update_ip_addrs(|addrs| {
136 addrs
137 .extend_from_slice(&addresses)
138 .expect("failed to set ip addresses");
139 });
140 let sockets = SocketSet::new(vec![]);
141 let handle = self.bridge.join(self.metadata.zone.mac).await?;
142 let kdev = AsyncRawSocketChannel::new(mtu, kdev)?;
143 Ok(NetworkStack {
144 tx: tx_receiver,
145 kdev,
146 udev,
147 interface: iface,
148 sockets,
149 nat,
150 bridge: handle,
151 })
152 }
153
154 pub async fn launch(self) -> Result<JoinHandle<()>> {
155 Ok(tokio::task::spawn(async move {
156 info!(
157 "launched network backend for krata zone {}",
158 self.metadata.uuid
159 );
160 if let Err(error) = self.run().await {
161 warn!(
162 "network backend for krata zone {} failed: {}",
163 self.metadata.uuid, error
164 );
165 }
166 }))
167 }
168}
169
170impl Drop for NetworkBackend {
171 fn drop(&mut self) {
172 info!(
173 "destroyed network backend for krata zone {}",
174 self.metadata.uuid
175 );
176 }
177}