Implement UDP getsockopt and setsockopt

This commit is contained in:
Yuke Peng
2024-08-24 12:00:42 +08:00
committed by Tate, Hongliang Tian
parent 468dae33f0
commit dc4df47007
5 changed files with 157 additions and 75 deletions

View File

@ -29,8 +29,8 @@ pub(super) enum SocketFamily {
impl AnyUnboundSocket {
pub fn new_tcp(observer: Weak<dyn Observer<()>>) -> Self {
let raw_tcp_socket = {
let rx_buffer = smoltcp::socket::tcp::SocketBuffer::new(vec![0u8; RECV_BUF_LEN]);
let tx_buffer = smoltcp::socket::tcp::SocketBuffer::new(vec![0u8; SEND_BUF_LEN]);
let rx_buffer = smoltcp::socket::tcp::SocketBuffer::new(vec![0u8; TCP_RECV_BUF_LEN]);
let tx_buffer = smoltcp::socket::tcp::SocketBuffer::new(vec![0u8; TCP_SEND_BUF_LEN]);
RawTcpSocket::new(rx_buffer, tx_buffer)
};
AnyUnboundSocket {
@ -44,7 +44,7 @@ impl AnyUnboundSocket {
let metadata = smoltcp::socket::udp::PacketMetadata::EMPTY;
let rx_buffer = smoltcp::socket::udp::PacketBuffer::new(
vec![metadata; UDP_METADATA_LEN],
vec![0u8; UDP_RECEIVE_PAYLOAD_LEN],
vec![0u8; UDP_RECV_PAYLOAD_LEN],
);
let tx_buffer = smoltcp::socket::udp::PacketBuffer::new(
vec![metadata; UDP_METADATA_LEN],
@ -209,10 +209,10 @@ impl Drop for AnyBoundSocketInner {
}
// For TCP
pub const RECV_BUF_LEN: usize = 65536;
pub const SEND_BUF_LEN: usize = 65536;
pub const TCP_RECV_BUF_LEN: usize = 65536;
pub const TCP_SEND_BUF_LEN: usize = 65536;
// For UDP
pub const UDP_SEND_PAYLOAD_LEN: usize = 65536;
pub const UDP_RECV_PAYLOAD_LEN: usize = 65536;
const UDP_METADATA_LEN: usize = 256;
const UDP_SEND_PAYLOAD_LEN: usize = 65536;
const UDP_RECEIVE_PAYLOAD_LEN: usize = 65536;

View File

@ -14,7 +14,8 @@ mod util;
mod virtio;
pub use any_socket::{
AnyBoundSocket, AnyUnboundSocket, RawTcpSocket, RawUdpSocket, RECV_BUF_LEN, SEND_BUF_LEN,
AnyBoundSocket, AnyUnboundSocket, RawTcpSocket, RawUdpSocket, TCP_RECV_BUF_LEN,
TCP_SEND_BUF_LEN, UDP_RECV_PAYLOAD_LEN, UDP_SEND_PAYLOAD_LEN,
};
pub use loopback::IfaceLoopback;
use ostd::sync::LocalIrqDisabled;

View File

@ -9,12 +9,15 @@ use super::{common::get_ephemeral_endpoint, IpEndpoint, UNSPECIFIED_LOCAL_ENDPOI
use crate::{
events::{IoEvents, Observer},
fs::{file_handle::FileLike, utils::StatusFlags},
match_sock_option_mut,
net::{
poll_ifaces,
socket::{
options::{Error as SocketError, SocketOption},
util::{
copy_message_from_user, copy_message_to_user, create_message_buffer,
send_recv_flags::SendRecvFlags, socket_addr::SocketAddr, MessageHeader,
options::SocketOptionSet, send_recv_flags::SendRecvFlags, socket_addr::SocketAddr,
MessageHeader,
},
Socket,
},
@ -27,7 +30,21 @@ use crate::{
mod bound;
mod unbound;
#[derive(Debug, Clone)]
struct OptionSet {
socket: SocketOptionSet,
// TODO: UDP option set
}
impl OptionSet {
fn new() -> Self {
let socket = SocketOptionSet::new_udp();
OptionSet { socket }
}
}
pub struct DatagramSocket {
options: RwLock<OptionSet>,
inner: RwLock<Takeable<Inner>>,
nonblocking: AtomicBool,
pollee: Pollee,
@ -80,6 +97,7 @@ impl DatagramSocket {
inner: RwLock::new(Takeable::new(Inner::Unbound(unbound_datagram))),
nonblocking: AtomicBool::new(nonblocking),
pollee,
options: RwLock::new(OptionSet::new()),
}
})
}
@ -352,6 +370,22 @@ impl Socket for DatagramSocket {
Ok((copied_bytes, message_header))
}
fn get_option(&self, option: &mut dyn SocketOption) -> Result<()> {
match_sock_option_mut!(option, {
socket_errors: SocketError => {
self.options.write().socket.get_and_clear_sock_errors(socket_errors);
return Ok(());
},
_ => ()
});
self.options.read().socket.get_option(option)
}
fn set_option(&self, option: &dyn SocketOption) -> Result<()> {
self.options.write().socket.set_option(option)
}
}
impl Observer<()> for DatagramSocket {

View File

@ -19,16 +19,11 @@ use crate::{
net::{
poll_ifaces,
socket::{
options::{
Error as SocketError, Linger, RecvBuf, ReuseAddr, ReusePort, SendBuf, SocketOption,
},
options::{Error as SocketError, SocketOption},
util::{
copy_message_from_user, copy_message_to_user, create_message_buffer,
options::{SocketOptionSet, MIN_RECVBUF, MIN_SENDBUF},
send_recv_flags::SendRecvFlags,
shutdown_cmd::SockShutdownCmd,
socket_addr::SocketAddr,
MessageHeader,
options::SocketOptionSet, send_recv_flags::SendRecvFlags,
shutdown_cmd::SockShutdownCmd, socket_addr::SocketAddr, MessageHeader,
},
Socket,
},
@ -561,15 +556,9 @@ impl Socket for StreamSocket {
}
fn get_option(&self, option: &mut dyn SocketOption) -> Result<()> {
// Note that the socket error has to be handled separately, because it is automatically
// cleared after reading.
match_sock_option_mut!(option, {
socket_errors: SocketError => {
let mut options = self.options.write();
let sock_errors = options.socket.sock_errors();
socket_errors.set(sock_errors);
options.socket.set_sock_errors(None);
self.options.write().socket.get_and_clear_sock_errors(socket_errors);
return Ok(());
},
_ => ()
@ -577,25 +566,12 @@ impl Socket for StreamSocket {
let options = self.options.read();
match options.socket.get_option(option) {
Err(err) if err.error() == Errno::ENOPROTOOPT => (),
res => return res.map(|_| ()),
}
match_sock_option_mut!(option, {
// Socket options:
socket_reuse_addr: ReuseAddr => {
let reuse_addr = options.socket.reuse_addr();
socket_reuse_addr.set(reuse_addr);
},
socket_send_buf: SendBuf => {
let send_buf = options.socket.send_buf();
socket_send_buf.set(send_buf);
},
socket_recv_buf: RecvBuf => {
let recv_buf = options.socket.recv_buf();
socket_recv_buf.set(recv_buf);
},
socket_reuse_port: ReusePort => {
let reuse_port = options.socket.reuse_port();
socket_reuse_port.set(reuse_port);
},
// TCP options:
tcp_no_delay: NoDelay => {
let no_delay = options.tcp.no_delay();
tcp_no_delay.set(no_delay);
@ -628,39 +604,14 @@ impl Socket for StreamSocket {
fn set_option(&self, option: &dyn SocketOption) -> Result<()> {
let mut options = self.options.write();
match options.socket.set_option(option) {
Err(err) if err.error() == Errno::ENOPROTOOPT => (),
res => return res,
}
// FIXME: here we have only set the value of the option, without actually
// making any real modifications.
match_sock_option_ref!(option, {
// Socket options:
socket_recv_buf: RecvBuf => {
let recv_buf = socket_recv_buf.get().unwrap();
if *recv_buf <= MIN_RECVBUF {
options.socket.set_recv_buf(MIN_RECVBUF);
} else {
options.socket.set_recv_buf(*recv_buf);
}
},
socket_send_buf: SendBuf => {
let send_buf = socket_send_buf.get().unwrap();
if *send_buf <= MIN_SENDBUF {
options.socket.set_send_buf(MIN_SENDBUF);
} else {
options.socket.set_send_buf(*send_buf);
}
},
socket_reuse_addr: ReuseAddr => {
let reuse_addr = socket_reuse_addr.get().unwrap();
options.socket.set_reuse_addr(*reuse_addr);
},
socket_reuse_port: ReusePort => {
let reuse_port = socket_reuse_port.get().unwrap();
options.socket.set_reuse_port(*reuse_port);
},
socket_linger: Linger => {
let linger = socket_linger.get().unwrap();
options.socket.set_linger(*linger);
},
// TCP options:
tcp_no_delay: NoDelay => {
let no_delay = tcp_no_delay.get().unwrap();
options.tcp.set_no_delay(*no_delay);

View File

@ -3,7 +3,13 @@
use core::time::Duration;
use crate::{
net::iface::{RECV_BUF_LEN, SEND_BUF_LEN},
match_sock_option_mut, match_sock_option_ref,
net::{
iface::{TCP_RECV_BUF_LEN, TCP_SEND_BUF_LEN, UDP_RECV_PAYLOAD_LEN, UDP_SEND_PAYLOAD_LEN},
socket::options::{
Error as SocketError, Linger, RecvBuf, ReuseAddr, ReusePort, SendBuf, SocketOption,
},
},
prelude::*,
};
@ -26,11 +32,101 @@ impl SocketOptionSet {
sock_errors: None,
reuse_addr: false,
reuse_port: false,
send_buf: SEND_BUF_LEN as u32,
recv_buf: RECV_BUF_LEN as u32,
send_buf: TCP_SEND_BUF_LEN as u32,
recv_buf: TCP_RECV_BUF_LEN as u32,
linger: LingerOption::default(),
}
}
/// Return the default socket level options for udp socket.
pub fn new_udp() -> Self {
Self {
sock_errors: None,
reuse_addr: false,
reuse_port: false,
send_buf: UDP_SEND_PAYLOAD_LEN as u32,
recv_buf: UDP_RECV_PAYLOAD_LEN as u32,
linger: LingerOption::default(),
}
}
/// Gets and clears the socket error.
///
/// When processing the `getsockopt` system call, the socket error is automatically cleared
/// after reading. This method should be called to provide this behavior.
pub fn get_and_clear_sock_errors(&mut self, option: &mut SocketError) {
option.set(self.sock_errors());
self.set_sock_errors(None);
}
/// Gets socket-level options.
///
/// Note that the socket error has to be handled separately, because it is automatically
/// cleared after reading. This method does not handle it. Instead,
/// [`Self::get_and_clear_socket_errors`] should be used.
pub fn get_option(&self, option: &mut dyn SocketOption) -> Result<()> {
match_sock_option_mut!(option, {
socket_reuse_addr: ReuseAddr => {
let reuse_addr = self.reuse_addr();
socket_reuse_addr.set(reuse_addr);
},
socket_send_buf: SendBuf => {
let send_buf = self.send_buf();
socket_send_buf.set(send_buf);
},
socket_recv_buf: RecvBuf => {
let recv_buf = self.recv_buf();
socket_recv_buf.set(recv_buf);
},
socket_reuse_port: ReusePort => {
let reuse_port = self.reuse_port();
socket_reuse_port.set(reuse_port);
},
socket_linger: Linger => {
let linger = self.linger();
socket_linger.set(linger);
},
_ => return_errno_with_message!(Errno::ENOPROTOOPT, "the socket option to get is unknown")
});
Ok(())
}
/// Sets socket-level options.
pub fn set_option(&mut self, option: &dyn SocketOption) -> Result<()> {
match_sock_option_ref!(option, {
socket_recv_buf: RecvBuf => {
let recv_buf = socket_recv_buf.get().unwrap();
if *recv_buf <= MIN_RECVBUF {
self.set_recv_buf(MIN_RECVBUF);
} else {
self.set_recv_buf(*recv_buf);
}
},
socket_send_buf: SendBuf => {
let send_buf = socket_send_buf.get().unwrap();
if *send_buf <= MIN_SENDBUF {
self.set_send_buf(MIN_SENDBUF);
} else {
self.set_send_buf(*send_buf);
}
},
socket_reuse_addr: ReuseAddr => {
let reuse_addr = socket_reuse_addr.get().unwrap();
self.set_reuse_addr(*reuse_addr);
},
socket_reuse_port: ReusePort => {
let reuse_port = socket_reuse_port.get().unwrap();
self.set_reuse_port(*reuse_port);
},
socket_linger: Linger => {
let linger = socket_linger.get().unwrap();
self.set_linger(*linger);
},
_ => return_errno_with_message!(Errno::ENOPROTOOPT, "the socket option to be set is unknown")
});
Ok(())
}
}
pub const MIN_SENDBUF: u32 = 2304;