From 4d60c715e683aaadf25d9f066bde805c725fefb4 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Thu, 3 Aug 2023 14:23:11 +0200 Subject: net: move tuntap from std example to separate crate. (#1737) --- examples/std/src/bin/net.rs | 5 +- examples/std/src/bin/net_dns.rs | 5 +- examples/std/src/bin/net_udp.rs | 5 +- examples/std/src/bin/tcp_accept.rs | 5 +- examples/std/src/tuntap.rs | 224 ------------------------------------- 5 files changed, 4 insertions(+), 240 deletions(-) delete mode 100644 examples/std/src/tuntap.rs (limited to 'examples/std/src') diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs index 3aadb029d..e0de14162 100644 --- a/examples/std/src/bin/net.rs +++ b/examples/std/src/bin/net.rs @@ -6,6 +6,7 @@ use clap::Parser; use embassy_executor::{Executor, Spawner}; use embassy_net::tcp::TcpSocket; use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; +use embassy_net_tuntap::TunTapDevice; use embassy_time::Duration; use embedded_io::asynch::Write; use heapless::Vec; @@ -13,10 +14,6 @@ use log::*; use rand_core::{OsRng, RngCore}; use static_cell::{make_static, StaticCell}; -#[path = "../tuntap.rs"] -mod tuntap; - -use crate::tuntap::TunTapDevice; #[derive(Parser)] #[clap(version = "1.0")] struct Opts { diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs index 65b5a2cd9..6c19874d5 100644 --- a/examples/std/src/bin/net_dns.rs +++ b/examples/std/src/bin/net_dns.rs @@ -6,15 +6,12 @@ use clap::Parser; use embassy_executor::{Executor, Spawner}; use embassy_net::dns::DnsQueryType; use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; +use embassy_net_tuntap::TunTapDevice; use heapless::Vec; use log::*; use rand_core::{OsRng, RngCore}; use static_cell::{make_static, StaticCell}; -#[path = "../tuntap.rs"] -mod tuntap; - -use crate::tuntap::TunTapDevice; #[derive(Parser)] #[clap(version = "1.0")] struct Opts { diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs index 3fc46156c..98dcc9925 100644 --- a/examples/std/src/bin/net_udp.rs +++ b/examples/std/src/bin/net_udp.rs @@ -4,15 +4,12 @@ use clap::Parser; use embassy_executor::{Executor, Spawner}; use embassy_net::udp::{PacketMetadata, UdpSocket}; use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; +use embassy_net_tuntap::TunTapDevice; use heapless::Vec; use log::*; use rand_core::{OsRng, RngCore}; use static_cell::{make_static, StaticCell}; -#[path = "../tuntap.rs"] -mod tuntap; - -use crate::tuntap::TunTapDevice; #[derive(Parser)] #[clap(version = "1.0")] struct Opts { diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs index df09986ac..0c920a3fb 100644 --- a/examples/std/src/bin/tcp_accept.rs +++ b/examples/std/src/bin/tcp_accept.rs @@ -7,6 +7,7 @@ use clap::Parser; use embassy_executor::{Executor, Spawner}; use embassy_net::tcp::TcpSocket; use embassy_net::{Config, Ipv4Address, Ipv4Cidr, Stack, StackResources}; +use embassy_net_tuntap::TunTapDevice; use embassy_time::{Duration, Timer}; use embedded_io::asynch::Write as _; use heapless::Vec; @@ -14,10 +15,6 @@ use log::*; use rand_core::{OsRng, RngCore}; use static_cell::{make_static, StaticCell}; -#[path = "../tuntap.rs"] -mod tuntap; - -use crate::tuntap::TunTapDevice; #[derive(Parser)] #[clap(version = "1.0")] struct Opts { diff --git a/examples/std/src/tuntap.rs b/examples/std/src/tuntap.rs deleted file mode 100644 index 167c3da5f..000000000 --- a/examples/std/src/tuntap.rs +++ /dev/null @@ -1,224 +0,0 @@ -use std::io; -use std::io::{Read, Write}; -use std::os::unix::io::{AsRawFd, RawFd}; -use std::task::Context; - -use async_io::Async; -use embassy_net_driver::{self, Capabilities, Driver, HardwareAddress, LinkState}; -use log::*; - -pub const SIOCGIFMTU: libc::c_ulong = 0x8921; -pub const _SIOCGIFINDEX: libc::c_ulong = 0x8933; -pub const _ETH_P_ALL: libc::c_short = 0x0003; -pub const TUNSETIFF: libc::c_ulong = 0x400454CA; -pub const _IFF_TUN: libc::c_int = 0x0001; -pub const IFF_TAP: libc::c_int = 0x0002; -pub const IFF_NO_PI: libc::c_int = 0x1000; - -const ETHERNET_HEADER_LEN: usize = 14; - -#[repr(C)] -#[derive(Debug)] -struct ifreq { - ifr_name: [libc::c_char; libc::IF_NAMESIZE], - ifr_data: libc::c_int, /* ifr_ifindex or ifr_mtu */ -} - -fn ifreq_for(name: &str) -> ifreq { - let mut ifreq = ifreq { - ifr_name: [0; libc::IF_NAMESIZE], - ifr_data: 0, - }; - for (i, byte) in name.as_bytes().iter().enumerate() { - ifreq.ifr_name[i] = *byte as libc::c_char - } - ifreq -} - -fn ifreq_ioctl(lower: libc::c_int, ifreq: &mut ifreq, cmd: libc::c_ulong) -> io::Result { - unsafe { - let res = libc::ioctl(lower, cmd as _, ifreq as *mut ifreq); - if res == -1 { - return Err(io::Error::last_os_error()); - } - } - - Ok(ifreq.ifr_data) -} - -#[derive(Debug)] -pub struct TunTap { - fd: libc::c_int, - mtu: usize, -} - -impl AsRawFd for TunTap { - fn as_raw_fd(&self) -> RawFd { - self.fd - } -} - -impl TunTap { - pub fn new(name: &str) -> io::Result { - unsafe { - let fd = libc::open( - "/dev/net/tun\0".as_ptr() as *const libc::c_char, - libc::O_RDWR | libc::O_NONBLOCK, - ); - if fd == -1 { - return Err(io::Error::last_os_error()); - } - - let mut ifreq = ifreq_for(name); - ifreq.ifr_data = IFF_TAP | IFF_NO_PI; - ifreq_ioctl(fd, &mut ifreq, TUNSETIFF)?; - - let socket = libc::socket(libc::AF_INET, libc::SOCK_DGRAM, libc::IPPROTO_IP); - if socket == -1 { - return Err(io::Error::last_os_error()); - } - - let ip_mtu = ifreq_ioctl(socket, &mut ifreq, SIOCGIFMTU); - libc::close(socket); - let ip_mtu = ip_mtu? as usize; - - // SIOCGIFMTU returns the IP MTU (typically 1500 bytes.) - // smoltcp counts the entire Ethernet packet in the MTU, so add the Ethernet header size to it. - let mtu = ip_mtu + ETHERNET_HEADER_LEN; - - Ok(TunTap { fd, mtu }) - } - } -} - -impl Drop for TunTap { - fn drop(&mut self) { - unsafe { - libc::close(self.fd); - } - } -} - -impl io::Read for TunTap { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let len = unsafe { libc::read(self.fd, buf.as_mut_ptr() as *mut libc::c_void, buf.len()) }; - if len == -1 { - Err(io::Error::last_os_error()) - } else { - Ok(len as usize) - } - } -} - -impl io::Write for TunTap { - fn write(&mut self, buf: &[u8]) -> io::Result { - let len = unsafe { libc::write(self.fd, buf.as_ptr() as *mut libc::c_void, buf.len()) }; - if len == -1 { - Err(io::Error::last_os_error()) - } else { - Ok(len as usize) - } - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -pub struct TunTapDevice { - device: Async, -} - -impl TunTapDevice { - pub fn new(name: &str) -> io::Result { - Ok(Self { - device: Async::new(TunTap::new(name)?)?, - }) - } -} - -impl Driver for TunTapDevice { - type RxToken<'a> = RxToken where Self: 'a; - type TxToken<'a> = TxToken<'a> where Self: 'a; - - fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { - let mut buf = vec![0; self.device.get_ref().mtu]; - loop { - match self.device.get_mut().read(&mut buf) { - Ok(n) => { - buf.truncate(n); - return Some(( - RxToken { buffer: buf }, - TxToken { - device: &mut self.device, - }, - )); - } - Err(e) if e.kind() == io::ErrorKind::WouldBlock => { - if !self.device.poll_readable(cx).is_ready() { - return None; - } - } - Err(e) => panic!("read error: {:?}", e), - } - } - } - - fn transmit(&mut self, _cx: &mut Context) -> Option> { - Some(TxToken { - device: &mut self.device, - }) - } - - fn capabilities(&self) -> Capabilities { - let mut caps = Capabilities::default(); - caps.max_transmission_unit = self.device.get_ref().mtu; - caps - } - - fn link_state(&mut self, _cx: &mut Context) -> LinkState { - LinkState::Up - } - - fn hardware_address(&self) -> HardwareAddress { - HardwareAddress::Ethernet([0x02, 0x03, 0x04, 0x05, 0x06, 0x07]) - } -} - -#[doc(hidden)] -pub struct RxToken { - buffer: Vec, -} - -impl embassy_net_driver::RxToken for RxToken { - fn consume(mut self, f: F) -> R - where - F: FnOnce(&mut [u8]) -> R, - { - f(&mut self.buffer) - } -} - -#[doc(hidden)] -pub struct TxToken<'a> { - device: &'a mut Async, -} - -impl<'a> embassy_net_driver::TxToken for TxToken<'a> { - fn consume(self, len: usize, f: F) -> R - where - F: FnOnce(&mut [u8]) -> R, - { - let mut buffer = vec![0; len]; - let result = f(&mut buffer); - - // todo handle WouldBlock with async - match self.device.get_mut().write(&buffer) { - Ok(_) => {} - Err(e) if e.kind() == io::ErrorKind::WouldBlock => info!("transmit WouldBlock"), - Err(e) => panic!("transmit error: {:?}", e), - } - - result - } -} -- cgit