Improve network performance by reducing ocalls
This commit is contained in:
parent
cd7a8cbc57
commit
7e0633116c
@ -4,6 +4,9 @@ use std::mem;
|
|||||||
|
|
||||||
use atomic::Atomic;
|
use atomic::Atomic;
|
||||||
|
|
||||||
|
use self::recv::Receiver;
|
||||||
|
use self::send::Sender;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::fs::{
|
use crate::fs::{
|
||||||
occlum_ocall_ioctl, AccessMode, CreationFlags, File, FileRef, HostFd, IoEvents, IoNotifier,
|
occlum_ocall_ioctl, AccessMode, CreationFlags, File, FileRef, HostFd, IoEvents, IoNotifier,
|
||||||
@ -15,12 +18,16 @@ mod recv;
|
|||||||
mod send;
|
mod send;
|
||||||
mod socket_file;
|
mod socket_file;
|
||||||
|
|
||||||
|
pub const SEND_BUF_SIZE: usize = 128 * 1024;
|
||||||
|
pub const RECV_BUF_SIZE: usize = 128 * 1024;
|
||||||
/// Native linux socket
|
/// Native linux socket
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct HostSocket {
|
pub struct HostSocket {
|
||||||
host_fd: HostFd,
|
host_fd: HostFd,
|
||||||
host_events: Atomic<IoEvents>,
|
host_events: Atomic<IoEvents>,
|
||||||
notifier: IoNotifier,
|
notifier: IoNotifier,
|
||||||
|
sender: SgxMutex<Sender>,
|
||||||
|
receiver: SgxMutex<Receiver>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HostSocket {
|
impl HostSocket {
|
||||||
@ -36,17 +43,21 @@ impl HostSocket {
|
|||||||
protocol
|
protocol
|
||||||
)) as FileDesc;
|
)) as FileDesc;
|
||||||
let host_fd = HostFd::new(raw_host_fd);
|
let host_fd = HostFd::new(raw_host_fd);
|
||||||
Ok(HostSocket::from_host_fd(host_fd))
|
Ok(HostSocket::from_host_fd(host_fd)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_host_fd(host_fd: HostFd) -> HostSocket {
|
fn from_host_fd(host_fd: HostFd) -> Result<HostSocket> {
|
||||||
let host_events = Atomic::new(IoEvents::empty());
|
let host_events = Atomic::new(IoEvents::empty());
|
||||||
let notifier = IoNotifier::new();
|
let notifier = IoNotifier::new();
|
||||||
Self {
|
let sender = SgxMutex::new(Sender::new()?);
|
||||||
|
let receiver = SgxMutex::new(Receiver::new()?);
|
||||||
|
Ok(Self {
|
||||||
host_fd,
|
host_fd,
|
||||||
host_events,
|
host_events,
|
||||||
notifier,
|
notifier,
|
||||||
}
|
sender,
|
||||||
|
receiver,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bind(&self, addr: &SockAddr) -> Result<()> {
|
pub fn bind(&self, addr: &SockAddr) -> Result<()> {
|
||||||
@ -83,7 +94,7 @@ impl HostSocket {
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
Ok((HostSocket::from_host_fd(host_fd), addr_option))
|
Ok((HostSocket::from_host_fd(host_fd)?, addr_option))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect(&self, addr: &Option<SockAddr>) -> Result<()> {
|
pub fn connect(&self, addr: &Option<SockAddr>) -> Result<()> {
|
||||||
|
@ -1,6 +1,18 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::untrusted::{SliceAsMutPtrAndLen, SliceAsPtrAndLen, UntrustedSliceAlloc};
|
use crate::untrusted::{SliceAsMutPtrAndLen, SliceAsPtrAndLen, UntrustedSliceAlloc};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Receiver {
|
||||||
|
alloc: UntrustedSliceAlloc,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Receiver {
|
||||||
|
pub fn new() -> Result<Self> {
|
||||||
|
let alloc = UntrustedSliceAlloc::new(RECV_BUF_SIZE)?;
|
||||||
|
Ok(Self { alloc })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HostSocket {
|
impl HostSocket {
|
||||||
pub fn recv(&self, buf: &mut [u8], flags: RecvFlags) -> Result<usize> {
|
pub fn recv(&self, buf: &mut [u8], flags: RecvFlags) -> Result<usize> {
|
||||||
let (bytes_recvd, _) = self.recvfrom(buf, flags)?;
|
let (bytes_recvd, _) = self.recvfrom(buf, flags)?;
|
||||||
@ -32,11 +44,24 @@ impl HostSocket {
|
|||||||
mut control: Option<&mut [u8]>,
|
mut control: Option<&mut [u8]>,
|
||||||
) -> Result<(usize, usize, usize, MsgHdrFlags)> {
|
) -> Result<(usize, usize, usize, MsgHdrFlags)> {
|
||||||
let data_length = data.iter().map(|s| s.len()).sum();
|
let data_length = data.iter().map(|s| s.len()).sum();
|
||||||
let u_allocator = UntrustedSliceAlloc::new(data_length)?;
|
let mut receiver: SgxMutexGuard<'_, Receiver>;
|
||||||
|
let mut ocall_alloc;
|
||||||
|
// Allocated slice in untrusted memory region
|
||||||
|
let u_allocator = if data_length > RECV_BUF_SIZE {
|
||||||
|
// Ocall allocator
|
||||||
|
ocall_alloc = UntrustedSliceAlloc::new(data_length)?;
|
||||||
|
&mut ocall_alloc
|
||||||
|
} else {
|
||||||
|
// Inner allocator, lock buffer until recv ocall completion
|
||||||
|
receiver = self.receiver.lock().unwrap();
|
||||||
|
&mut receiver.alloc
|
||||||
|
};
|
||||||
|
|
||||||
let mut u_data = {
|
let mut u_data = {
|
||||||
let mut bufs = Vec::new();
|
let mut bufs = Vec::new();
|
||||||
for ref buf in data.iter() {
|
for ref buf in data.iter() {
|
||||||
bufs.push(u_allocator.new_slice_mut(buf.len())?);
|
let u_slice = u_allocator.new_slice_mut(buf.len())?;
|
||||||
|
bufs.push(u_slice);
|
||||||
}
|
}
|
||||||
bufs
|
bufs
|
||||||
};
|
};
|
||||||
@ -52,6 +77,7 @@ impl HostSocket {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
u_allocator.reset();
|
||||||
Ok(retval)
|
Ok(retval)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,17 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Sender {
|
||||||
|
alloc: UntrustedSliceAlloc,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sender {
|
||||||
|
pub fn new() -> Result<Self> {
|
||||||
|
let alloc = UntrustedSliceAlloc::new(SEND_BUF_SIZE)?;
|
||||||
|
Ok(Self { alloc })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HostSocket {
|
impl HostSocket {
|
||||||
pub fn send(&self, buf: &[u8], flags: SendFlags) -> Result<usize> {
|
pub fn send(&self, buf: &[u8], flags: SendFlags) -> Result<usize> {
|
||||||
self.sendto(buf, flags, &None)
|
self.sendto(buf, flags, &None)
|
||||||
@ -24,16 +36,31 @@ impl HostSocket {
|
|||||||
control: Option<&[u8]>,
|
control: Option<&[u8]>,
|
||||||
) -> Result<usize> {
|
) -> Result<usize> {
|
||||||
let data_length = data.iter().map(|s| s.len()).sum();
|
let data_length = data.iter().map(|s| s.len()).sum();
|
||||||
let u_allocator = UntrustedSliceAlloc::new(data_length)?;
|
let mut sender: SgxMutexGuard<'_, Sender>;
|
||||||
|
let mut ocall_alloc;
|
||||||
|
// Allocated slice in untrusted memory region
|
||||||
|
let u_allocator = if data_length > SEND_BUF_SIZE {
|
||||||
|
// Ocall allocator
|
||||||
|
ocall_alloc = UntrustedSliceAlloc::new(data_length)?;
|
||||||
|
&mut ocall_alloc
|
||||||
|
} else {
|
||||||
|
// Inner allocator, lock buffer until send ocall completion
|
||||||
|
sender = self.sender.lock().unwrap();
|
||||||
|
&mut sender.alloc
|
||||||
|
};
|
||||||
|
|
||||||
let u_data = {
|
let u_data = {
|
||||||
let mut bufs = Vec::new();
|
let mut bufs = Vec::new();
|
||||||
for buf in data {
|
for buf in data {
|
||||||
bufs.push(u_allocator.new_slice(buf)?);
|
let u_slice = u_allocator.new_slice(buf)?;
|
||||||
|
bufs.push(u_slice);
|
||||||
}
|
}
|
||||||
bufs
|
bufs
|
||||||
};
|
};
|
||||||
|
|
||||||
self.do_sendmsg_untrusted_data(&u_data, flags, name, control)
|
let retval = self.do_sendmsg_untrusted_data(&u_data, flags, name, control);
|
||||||
|
u_allocator.reset();
|
||||||
|
retval
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_sendmsg_untrusted_data(
|
fn do_sendmsg_untrusted_data(
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use std::alloc::{AllocError, Allocator, Layout};
|
use std::alloc::{AllocError, Allocator, Layout};
|
||||||
|
use std::fmt;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
@ -21,6 +22,8 @@ pub struct UntrustedSliceAlloc {
|
|||||||
buf_pos: AtomicUsize,
|
buf_pos: AtomicUsize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for UntrustedSliceAlloc {}
|
||||||
|
|
||||||
impl UntrustedSliceAlloc {
|
impl UntrustedSliceAlloc {
|
||||||
pub fn new(buf_size: usize) -> Result<Self> {
|
pub fn new(buf_size: usize) -> Result<Self> {
|
||||||
if buf_size == 0 {
|
if buf_size == 0 {
|
||||||
@ -68,6 +71,10 @@ impl UntrustedSliceAlloc {
|
|||||||
let new_slice = unsafe { std::slice::from_raw_parts_mut(new_slice_ptr, new_slice_len) };
|
let new_slice = unsafe { std::slice::from_raw_parts_mut(new_slice_ptr, new_slice_len) };
|
||||||
Ok(UntrustedSlice { slice: new_slice })
|
Ok(UntrustedSlice { slice: new_slice })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
self.buf_pos.store(0, Ordering::Relaxed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for UntrustedSliceAlloc {
|
impl Drop for UntrustedSliceAlloc {
|
||||||
@ -84,6 +91,15 @@ impl Drop for UntrustedSliceAlloc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Debug for UntrustedSliceAlloc {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
f.debug_struct("UntrustedSliceAlloc")
|
||||||
|
.field("buf size", &self.buf_size)
|
||||||
|
.field("buf pos", &self.buf_pos.load(Ordering::Relaxed))
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct UntrustedSlice<'a> {
|
pub struct UntrustedSlice<'a> {
|
||||||
slice: &'a mut [u8],
|
slice: &'a mut [u8],
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user