Optimize vsock code structure

This commit is contained in:
Anmin Liu
2024-05-14 10:36:14 +00:00
committed by Tate, Hongliang Tian
parent 60dd17fdd3
commit 646406115e
16 changed files with 189 additions and 94 deletions

View File

@ -33,7 +33,7 @@ impl Connected {
pub fn from_connecting(connecting: Arc<Connecting>) -> Self {
Self {
connection: SpinLock::new(Connection::from_info(connecting.info())),
connection: SpinLock::new(Connection::new_from_info(connecting.info())),
id: connecting.id(),
pollee: Pollee::new(IoEvents::empty()),
}
@ -58,7 +58,7 @@ impl Connected {
match bytes_read {
0 => {
if !connection.peer_requested_shutdown {
if !connection.is_peer_requested_shutdown() {
return_errno_with_message!(Errno::EAGAIN, "the receive buffer is empty");
} else {
return_errno_with_message!(Errno::ECONNRESET, "the connection is reset");
@ -84,17 +84,26 @@ impl Connected {
let connection = self.connection.lock_irq_disabled();
// If buffer is now empty and the peer requested shutdown, finish shutting down the
// connection.
connection.peer_requested_shutdown && connection.buffer.is_empty()
connection.is_peer_requested_shutdown() && connection.buffer.is_empty()
}
pub fn is_closed(&self) -> bool {
let connection = self.connection.lock_irq_disabled();
connection.is_local_shutdown()
}
pub fn shutdown(&self, cmd: SockShutdownCmd) -> Result<()> {
// TODO: deal with cmd
if self.should_close() {
let connection = self.connection.lock_irq_disabled();
let mut connection = self.connection.lock_irq_disabled();
if connection.is_local_shutdown() {
return Ok(());
}
let vsockspace = VSOCK_GLOBAL.get().unwrap();
vsockspace.reset(&connection.info).unwrap();
vsockspace.remove_connected_socket(&self.id());
vsockspace.recycle_port(&self.local_addr().port);
connection.set_local_shutdown();
}
Ok(())
}
@ -113,8 +122,10 @@ impl Connected {
connection.add(bytes)
}
pub fn peer_requested_shutdown(&self) {
self.connection.lock_irq_disabled().peer_requested_shutdown = true
pub fn set_peer_requested_shutdown(&self) {
self.connection
.lock_irq_disabled()
.set_peer_requested_shutdown()
}
pub fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
@ -134,41 +145,69 @@ impl Connected {
impl Drop for Connected {
fn drop(&mut self) {
let connection = self.connection.lock_irq_disabled();
if connection.is_local_shutdown() {
return;
}
let vsockspace = VSOCK_GLOBAL.get().unwrap();
vsockspace.reset(&connection.info).unwrap();
vsockspace.remove_connected_socket(&self.id());
vsockspace.recycle_port(&self.local_addr().port);
}
}
pub struct Connection {
struct Connection {
info: ConnectionInfo,
buffer: HeapRb<u8>,
/// The peer sent a SHUTDOWN request, but we haven't yet responded with a RST because there is
/// still data in the buffer.
pub peer_requested_shutdown: bool,
peer_requested_shutdown: bool,
local_shutdown: bool,
}
impl Connection {
pub fn new(peer: VsockSocketAddr, local_port: u32) -> Self {
fn new(peer: VsockSocketAddr, local_port: u32) -> Self {
let mut info = ConnectionInfo::new(peer.into(), local_port);
info.buf_alloc = PER_CONNECTION_BUFFER_CAPACITY.try_into().unwrap();
Self {
info,
buffer: HeapRb::new(PER_CONNECTION_BUFFER_CAPACITY),
peer_requested_shutdown: false,
local_shutdown: false,
}
}
pub fn from_info(mut info: ConnectionInfo) -> Self {
fn is_peer_requested_shutdown(&self) -> bool {
self.peer_requested_shutdown
}
fn set_peer_requested_shutdown(&mut self) {
self.peer_requested_shutdown = true
}
fn is_local_shutdown(&self) -> bool {
self.local_shutdown
}
fn set_local_shutdown(&mut self) {
self.local_shutdown = true
}
fn new_from_info(mut info: ConnectionInfo) -> Self {
info.buf_alloc = PER_CONNECTION_BUFFER_CAPACITY.try_into().unwrap();
Self {
info,
buffer: HeapRb::new(PER_CONNECTION_BUFFER_CAPACITY),
peer_requested_shutdown: false,
local_shutdown: false,
}
}
pub fn update_for_event(&mut self, event: &VsockEvent) {
fn update_for_event(&mut self, event: &VsockEvent) {
self.info.update_for_event(event)
}
pub fn add(&mut self, bytes: &[u8]) -> bool {
fn add(&mut self, bytes: &[u8]) -> bool {
if bytes.len() > self.buffer.free_len() {
return false;
}

View File

@ -24,6 +24,7 @@ impl Connecting {
pollee: Pollee::new(IoEvents::empty()),
}
}
pub fn peer_addr(&self) -> VsockSocketAddr {
self.id.peer_addr
}
@ -35,15 +36,19 @@ impl Connecting {
pub fn id(&self) -> ConnectionID {
self.id
}
pub fn info(&self) -> ConnectionInfo {
self.info.lock_irq_disabled().clone()
}
pub fn update_info(&self, event: &VsockEvent) {
self.info.lock_irq_disabled().update_for_event(event)
}
pub fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.pollee.poll(mask, poller)
}
pub fn add_events(&self, events: IoEvents) {
self.pollee.add_events(events)
}
@ -53,5 +58,6 @@ impl Drop for Connecting {
fn drop(&mut self) {
let vsockspace = VSOCK_GLOBAL.get().unwrap();
vsockspace.recycle_port(&self.local_addr().port);
vsockspace.remove_connecting_socket(&self.local_addr());
}
}

View File

@ -44,7 +44,7 @@ impl Init {
} else {
return_errno_with_message!(Errno::EAGAIN, "cannot find unused high port");
}
} else if !vsockspace.insert_port(new_addr.port) {
} else if !vsockspace.bind_port(new_addr.port) {
return_errno_with_message!(Errno::EADDRNOTAVAIL, "the port in address is occupied");
}

View File

@ -27,6 +27,7 @@ impl Listen {
pub fn addr(&self) -> VsockSocketAddr {
self.addr
}
pub fn push_incoming(&self, connect: Arc<Connected>) -> Result<()> {
let mut incoming_connections = self.incoming_connection.lock_irq_disabled();
if incoming_connections.len() >= self.backlog {
@ -47,13 +48,14 @@ impl Listen {
Ok(connection)
}
pub fn poll(&self, mask: IoEvents, poller: Option<&Poller>) -> IoEvents {
self.pollee.poll(mask, poller)
}
pub fn update_io_events(&self) {
let can_accept = !self.incoming_connection.lock_irq_disabled().is_empty();
if can_accept {
let incomming_connection = self.incoming_connection.lock_irq_disabled();
if !incomming_connection.is_empty() {
self.pollee.add_events(IoEvents::IN);
} else {
self.pollee.del_events(IoEvents::IN);
@ -63,6 +65,8 @@ impl Listen {
impl Drop for Listen {
fn drop(&mut self) {
VSOCK_GLOBAL.get().unwrap().recycle_port(&self.addr.port);
let vsockspace = VSOCK_GLOBAL.get().unwrap();
vsockspace.recycle_port(&self.addr.port);
vsockspace.remove_listen_socket(&self.addr);
}
}

View File

@ -35,12 +35,14 @@ impl VsockStreamSocket {
is_nonblocking: AtomicBool::new(nonblocking),
}
}
pub(super) fn new_from_connected(connected: Arc<Connected>) -> Self {
Self {
status: RwLock::new(Status::Connected(connected)),
is_nonblocking: AtomicBool::new(false),
}
}
fn is_nonblocking(&self) -> bool {
self.is_nonblocking.load(Ordering::Relaxed)
}
@ -103,7 +105,8 @@ impl VsockStreamSocket {
VSOCK_GLOBAL
.get()
.unwrap()
.response(&connected.get_info())?;
.response(&connected.get_info())
.unwrap();
let socket = Arc::new(VsockStreamSocket::new_from_connected(connected));
Ok((socket, peer_addr.into()))
@ -123,7 +126,6 @@ impl VsockStreamSocket {
let peer_addr = self.peer_addr()?;
// If buffer is now empty and the peer requested shutdown, finish shutting down the
// connection.
// TODO: properly place the close request
if connected.should_close() {
if let Err(e) = self.shutdown(SockShutdownCmd::SHUT_RDWR) {
debug!("The error is {:?}", e);
@ -189,7 +191,7 @@ impl Socket for VsockStreamSocket {
}
// Since blocking mode is supported, there is no need to store the connecting status.
// TODO: Refactor when blocking mode is supported.
// TODO: Refactor when nonblocking mode is supported.
fn connect(&self, sockaddr: SocketAddr) -> Result<()> {
let init = match &*self.status.read() {
Status::Init(init) => init.clone(),
@ -223,7 +225,12 @@ impl Socket for VsockStreamSocket {
.poll(IoEvents::IN, Some(&poller))
.contains(IoEvents::IN)
{
poller.wait()?;
if let Err(e) = poller.wait() {
vsockspace
.remove_connecting_socket(&connecting.local_addr())
.unwrap();
return Err(e);
}
}
vsockspace