From 755f820c416058cdb8df6f5929eb65f3c6001e10 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Sun, 17 Mar 2019 00:33:05 +0800 Subject: [PATCH] Enable interrupt throttling, use spin before wait in sys_read and fix sys_bind, sys_poll for udp --- kernel/src/drivers/net/ixgbe.rs | 16 +++++- kernel/src/process/structs.rs | 2 +- kernel/src/syscall/net.rs | 92 ++++++++++++++++++--------------- 3 files changed, 67 insertions(+), 43 deletions(-) diff --git a/kernel/src/drivers/net/ixgbe.rs b/kernel/src/drivers/net/ixgbe.rs index ad798c4..9808c35 100644 --- a/kernel/src/drivers/net/ixgbe.rs +++ b/kernel/src/drivers/net/ixgbe.rs @@ -52,8 +52,10 @@ const IXGBE_CTRL: usize = 0x00000 / 4; const IXGBE_STATUS: usize = 0x00008 / 4; const IXGBE_CTRL_EXT: usize = 0x00018 / 4; const IXGBE_EICR: usize = 0x00800 / 4; +const IXGBE_EITR: usize = 0x00820 / 4; const IXGBE_EIMS: usize = 0x00880 / 4; const IXGBE_EIMC: usize = 0x00888 / 4; +const IXGBE_GPIE: usize = 0x00898 / 4; const IXGBE_IVAR: usize = 0x00900 / 4; const IXGBE_EIMC1: usize = 0x00A90 / 4; const IXGBE_EIMC2: usize = 0x00A91 / 4; @@ -725,9 +727,21 @@ pub fn ixgbe_init(header: usize, size: usize) { ixgbe[IXGBE_TXDCTL].write(ixgbe[IXGBE_TXDCTL].read() | 1 << 25); while ixgbe[IXGBE_TXDCTL].read() & (1 << 25) == 0 {} + // Interrupt Moderation + // Throttle interrupts + // Seems having good effect on tx bandwidth + // but bad effect on rx bandwidth + // CNT_WDIS | ITR Interval=100us + // if sys_read() spin more times, the interval here should be larger + // Linux use dynamic ETIR based on statistics + ixgbe[IXGBE_EITR].write(((100/2) << 3) | (1 << 31)); + // Enable interrupts - // map Tx0 to interrupt 0 + // map Rx0 to interrupt 0 ixgbe[IXGBE_IVAR].write(0b00000000_00000000_00000000_10000000); + // Disable general purpose interrupt + // We don't need them + ixgbe[IXGBE_GPIE].write(0); // clear all interrupt ixgbe[IXGBE_EICR].write(!0); diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index 709a079..5ef6f36 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -35,7 +35,7 @@ pub struct TcpSocketState { #[derive(Clone, Debug)] pub struct UdpSocketState { - pub remote_endpoint: Option, // remember remote endpoint for connect(0) + pub remote_endpoint: Option, // remember remote endpoint for connect() } #[derive(Clone, Debug)] diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index 5e43109..22f966c 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -81,7 +81,7 @@ pub fn sys_socket(domain: usize, socket_type: usize, protocol: usize) -> SysResu FileLike::Socket(SocketWrapper { handle: udp_handle, socket_type: SocketType::Udp(UdpSocketState { - remote_endpoint: None + remote_endpoint: None, }), }), ); @@ -154,36 +154,30 @@ pub fn sys_getsockopt( let proc = process(); proc.memory_set.check_mut_ptr(optlen)?; match level { - SOL_SOCKET => { - match optname { - SO_SNDBUF => { - proc.memory_set.check_mut_array(optval, 4)?; - unsafe { - *(optval as *mut u32) = TCP_SENDBUF as u32; - *optlen = 4; - } - Ok(0) - } - SO_RCVBUF => { - proc.memory_set.check_mut_array(optval, 4)?; - unsafe { - *(optval as *mut u32) = TCP_RECVBUF as u32; - *optlen = 4; - } - Ok(0) + SOL_SOCKET => match optname { + SO_SNDBUF => { + proc.memory_set.check_mut_array(optval, 4)?; + unsafe { + *(optval as *mut u32) = TCP_SENDBUF as u32; + *optlen = 4; } - _ => Err(SysError::ENOPROTOOPT) + Ok(0) } - } - IPPROTO_TCP => { - match optname { - TCP_CONGESTION => { - Ok(0) + SO_RCVBUF => { + proc.memory_set.check_mut_array(optval, 4)?; + unsafe { + *(optval as *mut u32) = TCP_RECVBUF as u32; + *optlen = 4; } - _ => Err(SysError::ENOPROTOOPT) + Ok(0) } - } - _ => Err(SysError::ENOPROTOOPT) + _ => Err(SysError::ENOPROTOOPT), + }, + IPPROTO_TCP => match optname { + TCP_CONGESTION => Ok(0), + _ => Err(SysError::ENOPROTOOPT), + }, + _ => Err(SysError::ENOPROTOOPT), } } @@ -293,7 +287,7 @@ pub fn sys_write_socket(proc: &mut Process, fd: usize, base: *const u8, len: usi let mut sockets = iface.sockets(); let mut socket = sockets.get::(wrapper.handle); - if !socket.endpoint().is_specified() { + if socket.endpoint().port == 0 { let v4_src = iface.ipv4_address().unwrap(); let temp_port = get_ephemeral_port(); socket @@ -333,7 +327,8 @@ pub fn sys_read_socket(proc: &mut Process, fd: usize, base: *mut u8, len: usize) let iface = &*(NET_DRIVERS.read()[0]); let wrapper = proc.get_socket(fd)?; if let SocketType::Tcp(_) = wrapper.socket_type { - loop { + spin_and_wait(&[&SOCKET_ACTIVITY], move || { + iface.poll(); let mut sockets = iface.sockets(); let mut socket = sockets.get::(wrapper.handle); @@ -346,18 +341,14 @@ pub fn sys_read_socket(proc: &mut Process, fd: usize, base: *mut u8, len: usize) drop(sockets); iface.poll(); - return Ok(size); + return Some(Ok(size)); } } } else { - return Err(SysError::ENOTCONN); + return Some(Err(SysError::ENOTCONN)); } - - // avoid deadlock - drop(socket); - drop(sockets); - SOCKET_ACTIVITY._wait() - } + None + }) } else if let SocketType::Udp(_) = wrapper.socket_type { loop { let mut sockets = iface.sockets(); @@ -443,7 +434,7 @@ pub fn sys_sendto( let mut sockets = iface.sockets(); let mut socket = sockets.get::(wrapper.handle); - if !socket.endpoint().is_specified() { + if socket.endpoint().port == 0 { let temp_port = get_ephemeral_port(); socket .bind(IpEndpoint::new(IpAddress::Ipv4(v4_src), temp_port)) @@ -482,7 +473,6 @@ pub fn sys_recvfrom( proc.memory_set.check_mut_array(buffer, len)?; let iface = &*(NET_DRIVERS.read()[0]); - debug!("sockets {:#?}", proc.files); let wrapper = proc.get_socket(fd)?; // TODO: move some part of these into one generic function @@ -597,6 +587,7 @@ pub fn sys_bind(fd: usize, addr: *const SockAddr, addr_len: usize) -> SysResult if endpoint.port == 0 { endpoint.port = get_ephemeral_port(); } + info!("sys_bind: fd: {} bind to {}", fd, endpoint); let iface = &*(NET_DRIVERS.read()[0]); let wrapper = &mut proc.get_socket_mut(fd)?; @@ -606,6 +597,13 @@ pub fn sys_bind(fd: usize, addr: *const SockAddr, addr_len: usize) -> SysResult is_listening: false, }); Ok(0) + } else if let SocketType::Udp(_) = wrapper.socket_type { + let mut sockets = iface.sockets(); + let mut socket = sockets.get::(wrapper.handle); + match socket.bind(endpoint) { + Ok(()) => Ok(0), + Err(_) => Err(SysError::EINVAL), + } } else { Err(SysError::EINVAL) } @@ -782,7 +780,7 @@ pub fn sys_getsockname(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> Sy let mut sockets = iface.sockets(); let socket = sockets.get::(wrapper.handle); let endpoint = socket.local_endpoint(); - if endpoint.is_specified() { + if endpoint.port != 0 { let sockaddr_in = SockAddr::from(socket.local_endpoint()); unsafe { sockaddr_in.write_to(&mut proc, addr, addr_len)?; @@ -796,7 +794,7 @@ pub fn sys_getsockname(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> Sy let mut sockets = iface.sockets(); let socket = sockets.get::(wrapper.handle); let endpoint = socket.endpoint(); - if endpoint.is_specified() { + if endpoint.port != 0 { let sockaddr_in = SockAddr::from(endpoint); unsafe { sockaddr_in.write_to(&mut proc, addr, addr_len)?; @@ -880,6 +878,18 @@ pub fn poll_socket(wrapper: &SocketWrapper) -> (bool, bool, bool) { output = true; } } + } else if let SocketType::Udp(_) = wrapper.socket_type { + let iface = &*(NET_DRIVERS.read()[0]); + let mut sockets = iface.sockets(); + let socket = sockets.get::(wrapper.handle); + + if socket.can_recv() { + input = true; + } + + if socket.can_send() { + output = true; + } } else { unimplemented!() }