adapt tun device to zerocopy (#57)

This commit is contained in:
Sijie.Sun
2024-04-25 23:25:37 +08:00
committed by GitHub
parent 3467890270
commit 57c9f11371
15 changed files with 405 additions and 150 deletions

View File

@@ -167,16 +167,41 @@ where
}
}
pub trait ZCPacketToBytes {
fn into_bytes(&self, zc_packet: ZCPacket) -> Result<Bytes, TunnelError>;
}
pub struct TcpZCPacketToBytes;
impl ZCPacketToBytes for TcpZCPacketToBytes {
fn into_bytes(&self, mut item: ZCPacket) -> Result<Bytes, TunnelError> {
let tcp_len = PEER_MANAGER_HEADER_SIZE + item.payload_len();
let Some(header) = item.mut_tcp_tunnel_header() else {
return Err(TunnelError::InvalidPacket("packet too short".to_string()));
};
header.len.set(tcp_len.try_into().unwrap());
Ok(item.into_bytes(ZCPacketType::TCP))
}
}
pin_project! {
pub struct FramedWriter<W> {
pub struct FramedWriter<W, C> {
#[pin]
writer: W,
sending_bufs: BufList<Bytes>,
associate_data: Option<Box<dyn Any + Send + 'static>>,
converter: C,
}
}
impl<W> FramedWriter<W> {
impl<W, C> FramedWriter<W, C> {
fn max_buffer_count(&self) -> usize {
64
}
}
impl<W> FramedWriter<W, TcpZCPacketToBytes> {
pub fn new(writer: W) -> Self {
Self::new_with_associate_data(writer, None)
}
@@ -188,18 +213,35 @@ impl<W> FramedWriter<W> {
FramedWriter {
writer,
sending_bufs: BufList::new(),
associate_data: associate_data,
associate_data,
converter: TcpZCPacketToBytes {},
}
}
fn max_buffer_count(&self) -> usize {
64
}
}
impl<W> Sink<SinkItem> for FramedWriter<W>
impl<W, C: ZCPacketToBytes + Send + 'static> FramedWriter<W, C> {
pub fn new_with_converter(writer: W, converter: C) -> Self {
Self::new_with_converter_and_associate_data(writer, converter, None)
}
pub fn new_with_converter_and_associate_data(
writer: W,
converter: C,
associate_data: Option<Box<dyn Any + Send + 'static>>,
) -> Self {
FramedWriter {
writer,
sending_bufs: BufList::new(),
associate_data,
converter,
}
}
}
impl<W, C> Sink<SinkItem> for FramedWriter<W, C>
where
W: AsyncWrite + Send + 'static,
C: ZCPacketToBytes + Send + 'static,
{
type Error = TunnelError;
@@ -216,15 +258,9 @@ where
}
}
fn start_send(self: Pin<&mut Self>, mut item: ZCPacket) -> Result<(), Self::Error> {
let tcp_len = PEER_MANAGER_HEADER_SIZE + item.payload_len();
let Some(header) = item.mut_tcp_tunnel_header() else {
return Err(TunnelError::InvalidPacket("packet too short".to_string()));
};
header.len.set(tcp_len.try_into().unwrap());
let item = item.into_bytes(ZCPacketType::TCP);
self.project().sending_bufs.push(item);
fn start_send(self: Pin<&mut Self>, item: ZCPacket) -> Result<(), Self::Error> {
let pinned = self.project();
pinned.sending_bufs.push(pinned.converter.into_bytes(item)?);
Ok(())
}

View File

@@ -52,6 +52,9 @@ pub enum TunnelError {
#[error("shutdown")]
Shutdown,
#[error("tunnel error: {0}")]
TunError(String),
}
pub type StreamT = packet_def::ZCPacket;

View File

@@ -161,12 +161,25 @@ impl ZCPacket {
ret
}
pub fn new_with_reserved_payload(cap: usize) -> Self {
let mut ret = Self::new_nic_packet();
ret.inner.reserve(cap);
let total_len = ret.packet_type.get_packet_offsets().payload_offset;
ret.inner.resize(total_len, 0);
ret
}
pub fn packet_type(&self) -> ZCPacketType {
self.packet_type
}
pub fn payload_offset(&self) -> usize {
self.packet_type.get_packet_offsets().payload_offset
}
pub fn mut_payload(&mut self) -> &mut [u8] {
&mut self.inner[self.packet_type.get_packet_offsets().payload_offset..]
let offset = self.payload_offset();
&mut self.inner[offset..]
}
pub fn mut_peer_manager_header(&mut self) -> Option<&mut PeerManagerHeader> {
@@ -207,7 +220,7 @@ impl ZCPacket {
// ref versions
pub fn payload(&self) -> &[u8] {
&self.inner[self.packet_type.get_packet_offsets().payload_offset..]
&self.inner[self.payload_offset()..]
}
pub fn peer_manager_header(&self) -> Option<&PeerManagerHeader> {
@@ -246,8 +259,7 @@ impl ZCPacket {
}
pub fn payload_len(&self) -> usize {
let payload_offset = self.packet_type.get_packet_offsets().payload_offset;
self.inner.len() - payload_offset
self.inner.len() - self.payload_offset()
}
pub fn buf_len(&self) -> usize {
@@ -307,6 +319,10 @@ impl ZCPacket {
pub fn inner(self) -> BytesMut {
self.inner
}
pub fn mut_inner(&mut self) -> &mut BytesMut {
&mut self.inner
}
}
#[cfg(test)]

View File

@@ -176,8 +176,8 @@ impl RingSink {
return Err(TunnelError::Shutdown);
}
log::trace!("id: {}, send buffer, buf: {:?}", self.tunnel.id(), &item);
self.tunnel.ring.push(item).unwrap();
tracing::trace!(id=?self.tunnel.id(), ?item, "send buffer");
let _ = self.tunnel.ring.push(item);
self.tunnel.notify_new_item();
Ok(())