Enable interrupt throttling, use spin before wait in sys_read and fix sys_bind, sys_poll for udp

master
Jiajie Chen 6 years ago
parent c6c76147d6
commit 755f820c41

@ -52,8 +52,10 @@ const IXGBE_CTRL: usize = 0x00000 / 4;
const IXGBE_STATUS: usize = 0x00008 / 4; const IXGBE_STATUS: usize = 0x00008 / 4;
const IXGBE_CTRL_EXT: usize = 0x00018 / 4; const IXGBE_CTRL_EXT: usize = 0x00018 / 4;
const IXGBE_EICR: usize = 0x00800 / 4; const IXGBE_EICR: usize = 0x00800 / 4;
const IXGBE_EITR: usize = 0x00820 / 4;
const IXGBE_EIMS: usize = 0x00880 / 4; const IXGBE_EIMS: usize = 0x00880 / 4;
const IXGBE_EIMC: usize = 0x00888 / 4; const IXGBE_EIMC: usize = 0x00888 / 4;
const IXGBE_GPIE: usize = 0x00898 / 4;
const IXGBE_IVAR: usize = 0x00900 / 4; const IXGBE_IVAR: usize = 0x00900 / 4;
const IXGBE_EIMC1: usize = 0x00A90 / 4; const IXGBE_EIMC1: usize = 0x00A90 / 4;
const IXGBE_EIMC2: usize = 0x00A91 / 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); ixgbe[IXGBE_TXDCTL].write(ixgbe[IXGBE_TXDCTL].read() | 1 << 25);
while ixgbe[IXGBE_TXDCTL].read() & (1 << 25) == 0 {} 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 // Enable interrupts
// map Tx0 to interrupt 0 // map Rx0 to interrupt 0
ixgbe[IXGBE_IVAR].write(0b00000000_00000000_00000000_10000000); 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 // clear all interrupt
ixgbe[IXGBE_EICR].write(!0); ixgbe[IXGBE_EICR].write(!0);

@ -35,7 +35,7 @@ pub struct TcpSocketState {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct UdpSocketState { pub struct UdpSocketState {
pub remote_endpoint: Option<IpEndpoint>, // remember remote endpoint for connect(0) pub remote_endpoint: Option<IpEndpoint>, // remember remote endpoint for connect()
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]

@ -81,7 +81,7 @@ pub fn sys_socket(domain: usize, socket_type: usize, protocol: usize) -> SysResu
FileLike::Socket(SocketWrapper { FileLike::Socket(SocketWrapper {
handle: udp_handle, handle: udp_handle,
socket_type: SocketType::Udp(UdpSocketState { socket_type: SocketType::Udp(UdpSocketState {
remote_endpoint: None remote_endpoint: None,
}), }),
}), }),
); );
@ -154,36 +154,30 @@ pub fn sys_getsockopt(
let proc = process(); let proc = process();
proc.memory_set.check_mut_ptr(optlen)?; proc.memory_set.check_mut_ptr(optlen)?;
match level { match level {
SOL_SOCKET => { SOL_SOCKET => match optname {
match optname { SO_SNDBUF => {
SO_SNDBUF => { proc.memory_set.check_mut_array(optval, 4)?;
proc.memory_set.check_mut_array(optval, 4)?; unsafe {
unsafe { *(optval as *mut u32) = TCP_SENDBUF as u32;
*(optval as *mut u32) = TCP_SENDBUF as u32; *optlen = 4;
*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)
} }
_ => Err(SysError::ENOPROTOOPT) Ok(0)
} }
} SO_RCVBUF => {
IPPROTO_TCP => { proc.memory_set.check_mut_array(optval, 4)?;
match optname { unsafe {
TCP_CONGESTION => { *(optval as *mut u32) = TCP_RECVBUF as u32;
Ok(0) *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 sockets = iface.sockets();
let mut socket = sockets.get::<UdpSocket>(wrapper.handle); let mut socket = sockets.get::<UdpSocket>(wrapper.handle);
if !socket.endpoint().is_specified() { if socket.endpoint().port == 0 {
let v4_src = iface.ipv4_address().unwrap(); let v4_src = iface.ipv4_address().unwrap();
let temp_port = get_ephemeral_port(); let temp_port = get_ephemeral_port();
socket 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 iface = &*(NET_DRIVERS.read()[0]);
let wrapper = proc.get_socket(fd)?; let wrapper = proc.get_socket(fd)?;
if let SocketType::Tcp(_) = wrapper.socket_type { if let SocketType::Tcp(_) = wrapper.socket_type {
loop { spin_and_wait(&[&SOCKET_ACTIVITY], move || {
iface.poll();
let mut sockets = iface.sockets(); let mut sockets = iface.sockets();
let mut socket = sockets.get::<TcpSocket>(wrapper.handle); let mut socket = sockets.get::<TcpSocket>(wrapper.handle);
@ -346,18 +341,14 @@ pub fn sys_read_socket(proc: &mut Process, fd: usize, base: *mut u8, len: usize)
drop(sockets); drop(sockets);
iface.poll(); iface.poll();
return Ok(size); return Some(Ok(size));
} }
} }
} else { } else {
return Err(SysError::ENOTCONN); return Some(Err(SysError::ENOTCONN));
} }
None
// avoid deadlock })
drop(socket);
drop(sockets);
SOCKET_ACTIVITY._wait()
}
} else if let SocketType::Udp(_) = wrapper.socket_type { } else if let SocketType::Udp(_) = wrapper.socket_type {
loop { loop {
let mut sockets = iface.sockets(); let mut sockets = iface.sockets();
@ -443,7 +434,7 @@ pub fn sys_sendto(
let mut sockets = iface.sockets(); let mut sockets = iface.sockets();
let mut socket = sockets.get::<UdpSocket>(wrapper.handle); let mut socket = sockets.get::<UdpSocket>(wrapper.handle);
if !socket.endpoint().is_specified() { if socket.endpoint().port == 0 {
let temp_port = get_ephemeral_port(); let temp_port = get_ephemeral_port();
socket socket
.bind(IpEndpoint::new(IpAddress::Ipv4(v4_src), temp_port)) .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)?; proc.memory_set.check_mut_array(buffer, len)?;
let iface = &*(NET_DRIVERS.read()[0]); let iface = &*(NET_DRIVERS.read()[0]);
debug!("sockets {:#?}", proc.files);
let wrapper = proc.get_socket(fd)?; let wrapper = proc.get_socket(fd)?;
// TODO: move some part of these into one generic function // 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 { if endpoint.port == 0 {
endpoint.port = get_ephemeral_port(); endpoint.port = get_ephemeral_port();
} }
info!("sys_bind: fd: {} bind to {}", fd, endpoint);
let iface = &*(NET_DRIVERS.read()[0]); let iface = &*(NET_DRIVERS.read()[0]);
let wrapper = &mut proc.get_socket_mut(fd)?; 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, is_listening: false,
}); });
Ok(0) Ok(0)
} else if let SocketType::Udp(_) = wrapper.socket_type {
let mut sockets = iface.sockets();
let mut socket = sockets.get::<UdpSocket>(wrapper.handle);
match socket.bind(endpoint) {
Ok(()) => Ok(0),
Err(_) => Err(SysError::EINVAL),
}
} else { } else {
Err(SysError::EINVAL) 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 mut sockets = iface.sockets();
let socket = sockets.get::<TcpSocket>(wrapper.handle); let socket = sockets.get::<TcpSocket>(wrapper.handle);
let endpoint = socket.local_endpoint(); let endpoint = socket.local_endpoint();
if endpoint.is_specified() { if endpoint.port != 0 {
let sockaddr_in = SockAddr::from(socket.local_endpoint()); let sockaddr_in = SockAddr::from(socket.local_endpoint());
unsafe { unsafe {
sockaddr_in.write_to(&mut proc, addr, addr_len)?; 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 mut sockets = iface.sockets();
let socket = sockets.get::<UdpSocket>(wrapper.handle); let socket = sockets.get::<UdpSocket>(wrapper.handle);
let endpoint = socket.endpoint(); let endpoint = socket.endpoint();
if endpoint.is_specified() { if endpoint.port != 0 {
let sockaddr_in = SockAddr::from(endpoint); let sockaddr_in = SockAddr::from(endpoint);
unsafe { unsafe {
sockaddr_in.write_to(&mut proc, addr, addr_len)?; sockaddr_in.write_to(&mut proc, addr, addr_len)?;
@ -880,6 +878,18 @@ pub fn poll_socket(wrapper: &SocketWrapper) -> (bool, bool, bool) {
output = true; 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::<UdpSocket>(wrapper.handle);
if socket.can_recv() {
input = true;
}
if socket.can_send() {
output = true;
}
} else { } else {
unimplemented!() unimplemented!()
} }

Loading…
Cancel
Save