Skip to content

Commit a3926c4

Browse files
committed
catpowder: remove type annotations and refactor
Reduced visual clutter and simplified logic.
1 parent b934096 commit a3926c4

6 files changed

Lines changed: 108 additions & 120 deletions

File tree

src/catnip/runtime/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ impl PhysicalLayer for SharedDPDKRuntime {
372372
}
373373

374374
impl DemiMemoryAllocator for SharedDPDKRuntime {
375-
fn get_max_buffer_size_bytes(&self) -> usize {
375+
fn max_buffer_size_bytes(&self) -> usize {
376376
self.max_body_size
377377
}
378378

src/catpowder/linux/mod.rs

Lines changed: 45 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ pub struct LinuxRuntime {
4444

4545
impl LinuxRuntime {
4646
pub fn new(config: &Config) -> Result<Self, Fail> {
47-
let mac_addr: [u8; 6] = [0; 6];
48-
let ifindex: i32 = match Self::get_ifindex(&config.local_interface_name()?) {
49-
Ok(ifindex) => ifindex,
50-
Err(_) => return Err(Fail::new(libc::EINVAL, "could not parse ifindex")),
51-
};
52-
let socket: RawSocket = RawSocket::new()?;
53-
let sockaddr: RawSocketAddr = RawSocketAddr::new(ifindex, &mac_addr);
54-
socket.bind(&sockaddr)?;
47+
let mac_addr = [0; 6];
48+
49+
let ifindex = Self::ifindex_for(&config.local_interface_name()?)
50+
.map_err(|_| Fail::new(libc::EINVAL, "could not parse ifindex"))?;
51+
52+
let socket = RawSocket::new()?;
53+
let bind_addr = RawSocketAddr::new(ifindex, &mac_addr);
54+
socket.bind(&bind_addr)?;
5555

5656
let max_body_size = config.mtu()? as usize - MAX_HEADER_SIZE;
5757

@@ -62,8 +62,8 @@ impl LinuxRuntime {
6262
})
6363
}
6464

65-
fn get_ifindex(ifname: &str) -> Result<i32, ParseIntError> {
66-
let path: String = format!("/sys/class/net/{}/ifindex", ifname);
65+
fn ifindex_for(ifname: &str) -> Result<i32, ParseIntError> {
66+
let path = format!("/sys/class/net/{}/ifindex", ifname);
6767
expect_ok!(fs::read_to_string(path), "could not read ifname")
6868
.trim()
6969
.parse()
@@ -75,7 +75,7 @@ impl LinuxRuntime {
7575
//======================================================================================================================
7676

7777
impl DemiMemoryAllocator for LinuxRuntime {
78-
fn get_max_buffer_size_bytes(&self) -> usize {
78+
fn max_buffer_size_bytes(&self) -> usize {
7979
self.max_body_size
8080
}
8181

@@ -87,55 +87,50 @@ impl DemiMemoryAllocator for LinuxRuntime {
8787
impl Runtime for LinuxRuntime {}
8888

8989
impl PhysicalLayer for LinuxRuntime {
90-
fn transmit(&mut self, pkts: ArrayVec<DemiBuffer, MAX_BATCH_SIZE_NUM_PACKETS>) -> Result<(), Fail> {
91-
for pkt in pkts {
92-
// We clone the packet so as to not remove the ethernet header from the outgoing message.
93-
let header = Ethernet2Header::parse_and_strip(&mut pkt.clone()).unwrap();
94-
let dest_addr_arr: [u8; 6] = header.dst_addr().to_array();
95-
let dest_sockaddr: RawSocketAddr = RawSocketAddr::new(self.ifindex, &dest_addr_arr);
96-
97-
match self.socket.sendto(&pkt, &dest_sockaddr) {
98-
Ok(size) if size == pkt.len() => (),
99-
Ok(size) => {
100-
let cause = format!(
101-
"Incorrect number of bytes sent: packet_size={:?} sent={:?}",
102-
pkt.len(),
103-
size
104-
);
90+
fn transmit(&mut self, packets: ArrayVec<DemiBuffer, MAX_BATCH_SIZE_NUM_PACKETS>) -> Result<(), Fail> {
91+
for packet in packets {
92+
// Parse header but keep original packet untouched for sending by cloning it.
93+
let header = Ethernet2Header::parse_and_strip(&mut packet.clone()).unwrap();
94+
let dst_mac = header.dst_addr().to_array();
95+
let addr = RawSocketAddr::new(self.ifindex, &dst_mac);
96+
97+
match self.socket.sendto(&packet, &addr) {
98+
Ok(n) if n == packet.len() => (),
99+
Ok(n) => {
100+
let cause = format!("transmit: partial send: packet_size={:?} sent={:?}", packet.len(), n);
105101
warn!("{}", cause);
106102
return Err(Fail::new(libc::EAGAIN, &cause));
107103
},
108104
Err(e) => {
109-
let cause = "send failed";
110-
warn!("transmit(): {} {:?}", cause, e);
111-
return Err(Fail::new(libc::EIO, &cause));
105+
warn!("transmit(): send failed: {:?}", e);
106+
return Err(Fail::new(libc::EIO, "send failed"));
112107
},
113108
}
114109
}
115110
Ok(())
116111
}
117112

118-
// TODO: This routine currently only tries to receive a single packet buffer, not a batch of them.
113+
// Only receives one packet for now.
114+
// TODO: Support receiving multiple packets in a single call.
115+
// TODO: Remove extra copy of the packet.
116+
// TODO: Change to use `DemiBuffer` directly instead of `MaybeUninit<u8>`.
119117
fn receive(&mut self) -> Result<ArrayVec<DemiBuffer, MAX_BATCH_SIZE_NUM_PACKETS>, Fail> {
120-
// TODO: This routine contains an extra copy of the entire incoming packet that could potentially be removed.
121-
122-
// TODO: change this function to operate directly on DemiBuffer rather than on MaybeUninit<u8>.
123-
124-
// This use-case is an example for MaybeUninit in the docs.
125-
let mut out: [MaybeUninit<u8>; limits::RECVBUF_SIZE_MAX] =
126-
[unsafe { MaybeUninit::uninit().assume_init() }; limits::RECVBUF_SIZE_MAX];
127-
if let Ok((nbytes, _origin_addr)) = self.socket.recvfrom(&mut out[..]) {
128-
let mut ret: ArrayVec<DemiBuffer, MAX_BATCH_SIZE_NUM_PACKETS> = ArrayVec::new();
129-
unsafe {
130-
let bytes: [u8; limits::RECVBUF_SIZE_MAX] =
131-
mem::transmute::<[MaybeUninit<u8>; limits::RECVBUF_SIZE_MAX], [u8; limits::RECVBUF_SIZE_MAX]>(out);
132-
let mut dbuf: DemiBuffer = DemiBuffer::from_slice(&bytes)?;
133-
dbuf.trim(limits::RECVBUF_SIZE_MAX - nbytes)?;
134-
ret.push(dbuf);
135-
}
136-
Ok(ret)
137-
} else {
138-
Ok(ArrayVec::new())
139-
}
118+
let mut recv_buffer = [unsafe { MaybeUninit::uninit().assume_init() }; limits::RECVBUF_SIZE_MAX];
119+
120+
let (nbytes, _src) = match self.socket.recvfrom(&mut recv_buffer) {
121+
Ok(res) => res,
122+
Err(_) => return Ok(ArrayVec::new()),
123+
};
124+
125+
let bytes = unsafe {
126+
mem::transmute::<[MaybeUninit<u8>; limits::RECVBUF_SIZE_MAX], [u8; limits::RECVBUF_SIZE_MAX]>(recv_buffer)
127+
};
128+
129+
let mut packet = DemiBuffer::from_slice(&bytes)?;
130+
packet.trim(limits::RECVBUF_SIZE_MAX - nbytes)?;
131+
132+
let mut packets = ArrayVec::new();
133+
packets.push(packet);
134+
Ok(packets)
140135
}
141136
}

src/catpowder/linux/rawsocket/rawsockaddr.rs

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use ::std::mem;
1010
use libc::sockaddr;
1111

1212
//======================================================================================================================
13-
// Constants & Structures
13+
// Structures
1414
//======================================================================================================================
1515

1616
#[derive(Clone, Copy)]
@@ -21,15 +21,15 @@ pub struct RawSocketAddr(libc::sockaddr_ll);
2121
//======================================================================================================================
2222

2323
impl RawSocketAddr {
24-
pub fn new(ifindex: i32, mac_addr: &[u8; 6]) -> Self {
25-
// Pad MAC address.
26-
let mut addr: [u8; 8] = [0_u8; 8];
27-
addr[..6].copy_from_slice(mac_addr);
24+
pub fn new(ifidx: i32, mac: &[u8; 6]) -> Self {
25+
// Pad MAC address to 8 bytes
26+
let mut addr = [0u8; 8];
27+
addr[..6].copy_from_slice(mac);
2828

2929
RawSocketAddr(libc::sockaddr_ll {
30-
sll_family: libc::AF_PACKET.try_into().unwrap(),
30+
sll_family: libc::AF_PACKET as u16,
3131
sll_protocol: (libc::ETH_P_ALL as u16).to_be(),
32-
sll_ifindex: ifindex,
32+
sll_ifindex: ifidx,
3333
sll_hatype: 0,
3434
sll_pkttype: 0,
3535
sll_halen: libc::ETH_ALEN as u8,
@@ -38,19 +38,15 @@ impl RawSocketAddr {
3838
}
3939

4040
pub fn as_sockaddr_ptr(&self) -> (*const sockaddr, Socklen) {
41-
let sockaddr_ptr: *const sockaddr =
42-
unsafe { mem::transmute::<*const libc::sockaddr_ll, *const sockaddr>(&self.0) };
43-
let sockaddr_len: Socklen = mem::size_of::<libc::sockaddr_ll>() as u32;
44-
45-
(sockaddr_ptr, sockaddr_len)
41+
let ptr = unsafe { mem::transmute::<*const libc::sockaddr_ll, *const sockaddr>(&self.0) };
42+
let len = mem::size_of::<libc::sockaddr_ll>() as u32;
43+
(ptr, len)
4644
}
4745

48-
pub fn as_sockaddr_mut_ptr(&mut self) -> (*mut sockaddr, Socklen) {
49-
let sockaddr_ptr: *mut sockaddr =
50-
unsafe { mem::transmute::<*mut libc::sockaddr_ll, *mut sockaddr>(&mut self.0) };
51-
let sockaddr_len: Socklen = mem::size_of::<libc::sockaddr_ll>() as u32;
52-
53-
(sockaddr_ptr, sockaddr_len)
46+
pub fn as_sockaddr_ptr_mut(&mut self) -> (*mut sockaddr, Socklen) {
47+
let ptr = unsafe { mem::transmute::<*mut libc::sockaddr_ll, *mut sockaddr>(&mut self.0) };
48+
let len = mem::size_of::<libc::sockaddr_ll>() as u32;
49+
(ptr, len)
5450
}
5551
}
5652

@@ -60,7 +56,6 @@ impl RawSocketAddr {
6056

6157
impl Default for RawSocketAddr {
6258
fn default() -> Self {
63-
let addr: libc::sockaddr_ll = unsafe { mem::zeroed() };
64-
Self(addr)
59+
Self(unsafe { mem::zeroed() })
6560
}
6661
}

src/catpowder/linux/rawsocket/rawsocket.rs

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@ use crate::{
1111
runtime::fail::Fail,
1212
};
1313
use ::std::{mem, mem::MaybeUninit};
14-
use libc::sockaddr;
1514

1615
//======================================================================================================================
17-
// Constants & Structures
16+
// Structures
1817
//======================================================================================================================
1918

2019
pub struct RawSocket(libc::c_int);
@@ -25,27 +24,24 @@ pub struct RawSocket(libc::c_int);
2524

2625
impl RawSocket {
2726
pub fn new() -> Result<Self, Fail> {
28-
let domain: i32 = libc::AF_PACKET; // Do not parse any headers.
29-
let ty: i32 = libc::SOCK_RAW | libc::SOCK_NONBLOCK; // Non-blocking, raw socket.
30-
let protocol: i32 = libc::ETH_P_ALL; // Accept packet from all protocols.
31-
let sockfd: i32 = unsafe { libc::socket(domain, ty, protocol) };
27+
let domain = libc::AF_PACKET; // raw packet socket, no header parsing
28+
let ty = libc::SOCK_RAW | libc::SOCK_NONBLOCK; // raw, non-blocking socket
29+
let protocol = libc::ETH_P_ALL; // all protocols
3230

33-
// Check if we failed to create the underlying raw socket.
34-
if sockfd == -1 {
31+
let fd = unsafe { libc::socket(domain, ty, protocol) };
32+
if fd == -1 {
3533
return Err(Fail::new(libc::EAGAIN, "failed to create raw socket"));
3634
}
37-
trace!("Creating raw socket with fd={:?}", sockfd);
38-
Ok(RawSocket(sockfd))
35+
36+
trace!("created raw socket with fd={:?}", fd);
37+
Ok(RawSocket(fd))
3938
}
4039

41-
// Binds a socket to a raw address.
40+
// Binds the socket to a raw address.
4241
pub fn bind(&self, addr: &RawSocketAddr) -> Result<(), Fail> {
43-
let ret: i32 = unsafe {
44-
let (sockaddr_ptr, address_len): (*const sockaddr, Socklen) = addr.as_sockaddr_ptr();
45-
libc::bind(self.0, sockaddr_ptr, address_len)
46-
};
42+
let (ptr, len) = addr.as_sockaddr_ptr();
4743

48-
// Check if we failed to bind the underlying raw socket.
44+
let ret = unsafe { libc::bind(self.0, ptr, len) };
4945
if ret == -1 {
5046
return Err(Fail::new(libc::EAGAIN, "failed to bind raw socket"));
5147
}
@@ -54,63 +50,65 @@ impl RawSocket {
5450
}
5551

5652
/// Sends data through a raw socket.
57-
pub fn sendto(&self, buf: &[u8], rawaddr: &RawSocketAddr) -> Result<usize, Fail> {
58-
let buf_len: usize = buf.len();
59-
let buf_ptr: *const libc::c_void = buf.as_ptr() as *const libc::c_void;
60-
let (addr_ptr, addrlen): (*const sockaddr, Socklen) = rawaddr.as_sockaddr_ptr();
61-
62-
let nbytes: i32 =
63-
unsafe { libc::sendto(self.0, buf_ptr, buf_len, libc::MSG_DONTWAIT, addr_ptr, addrlen) as i32 };
53+
pub fn sendto(&self, data: &[u8], rawaddr: &RawSocketAddr) -> Result<usize, Fail> {
54+
let (addr_ptr, addr_len) = rawaddr.as_sockaddr_ptr();
55+
let ret = unsafe {
56+
libc::sendto(
57+
self.0,
58+
data.as_ptr() as *const libc::c_void,
59+
data.len(),
60+
libc::MSG_DONTWAIT,
61+
addr_ptr,
62+
addr_len,
63+
)
64+
};
6465

65-
// Check if we failed to send data through raw socket.
66-
if nbytes == -1 {
66+
if ret == -1 {
6767
return Err(Fail::new(libc::EAGAIN, "failed to send data through raw socket"));
6868
}
6969

70-
Ok(nbytes as usize)
70+
Ok(ret as usize)
7171
}
7272

73-
/// Receives data from a raw socket.
74-
pub fn recvfrom(&self, buf: &[MaybeUninit<u8>]) -> Result<(usize, RawSocketAddr), Fail> {
75-
let buf_ptr: *mut libc::c_void = buf.as_ptr() as *mut libc::c_void;
76-
let buf_len: usize = buf.len();
77-
let mut addrlen: Socklen = mem::size_of::<SockAddrIn>() as u32;
78-
let mut rawaddr: RawSocketAddr = RawSocketAddr::default();
79-
let addrlen_ptr: *mut Socklen = &mut addrlen as *mut Socklen;
80-
let (addr_ptr, _): (*mut sockaddr, Socklen) = rawaddr.as_sockaddr_mut_ptr();
73+
/// Receive data from a raw socket.
74+
pub fn recvfrom(&self, recv_buffer: &[MaybeUninit<u8>]) -> Result<(usize, RawSocketAddr), Fail> {
75+
let ptr = recv_buffer.as_ptr() as *mut libc::c_void;
76+
let mut addrlen = mem::size_of::<SockAddrIn>() as u32;
77+
let mut rawaddr = RawSocketAddr::default();
78+
let (addr_ptr, _) = rawaddr.as_sockaddr_ptr_mut();
79+
let addrlen_ptr = &mut addrlen as *mut Socklen;
8180

82-
let nbytes: i32 = unsafe {
81+
let ret = unsafe {
8382
libc::recvfrom(
8483
self.0,
85-
buf_ptr,
86-
buf_len,
84+
ptr,
85+
recv_buffer.len(),
8786
libc::MSG_DONTWAIT,
8887
addr_ptr,
8988
addrlen_ptr as *mut u32,
9089
) as i32
9190
};
9291

93-
// Check if we failed to receive data from raw socket.
94-
if nbytes == -1 {
92+
if ret == -1 {
9593
return Err(Fail::new(libc::EAGAIN, "failed to receive data from raw socket"));
9694
}
9795

98-
Ok((nbytes as usize, rawaddr))
96+
Ok((ret as usize, rawaddr))
9997
}
10098
}
10199

102100
//======================================================================================================================
103101
// Trait Implementations
104102
//======================================================================================================================
105103

106-
/// Closes the raw socket.
107104
impl Drop for RawSocket {
108105
fn drop(&mut self) {
109-
if unsafe { libc::close(self.0) } < 0 {
110-
let errno: libc::c_int = unsafe { *libc::__errno_location() };
111-
warn!("could not close raw socket (fd={:?}): {:?}", self.0, errno);
106+
let ret = unsafe { libc::close(self.0) };
107+
if ret < 0 {
108+
let errno = unsafe { *libc::__errno_location() };
109+
warn!("failed to close raw socket (fd={}): {}", self.0, errno);
112110
} else {
113-
trace!("Closing raw socket fd={:?}", self.0)
111+
trace!("closed raw socket fd={}", self.0)
114112
}
115113
}
116114
}

src/catpowder/win/runtime.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ impl PhysicalLayer for SharedCatpowderRuntime {
195195

196196
/// Memory runtime trait implementation for XDP Runtime.
197197
impl DemiMemoryAllocator for SharedCatpowderRuntime {
198-
fn get_max_buffer_size_bytes(&self) -> usize {
198+
fn max_buffer_size_bytes(&self) -> usize {
199199
self.0.max_body_size
200200
}
201201

src/runtime/memory/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub use self::{buffer_pool::*, demibuffer::*};
2828
//======================================================================================================================
2929

3030
pub trait DemiMemoryAllocator {
31-
fn get_max_buffer_size_bytes(&self) -> usize {
31+
fn max_buffer_size_bytes(&self) -> usize {
3232
u16::MAX as usize
3333
}
3434

@@ -76,11 +76,11 @@ pub fn sgaalloc<M: DemiMemoryAllocator>(size: usize, mem_alloc: &M) -> Result<de
7676
}
7777

7878
// First allocate the underlying DemiBuffer.
79-
if size > mem_alloc.get_max_buffer_size_bytes() * DEMI_SGARRAY_MAXLEN {
79+
if size > mem_alloc.max_buffer_size_bytes() * DEMI_SGARRAY_MAXLEN {
8080
return Err(Fail::new(libc::EINVAL, "size too large for a single demi_sgaseg_t"));
8181
}
8282
// Calculate the number of DemiBuffers to allocate.
83-
let max_buffer_size_bytes: usize = mem_alloc.get_max_buffer_size_bytes();
83+
let max_buffer_size_bytes: usize = mem_alloc.max_buffer_size_bytes();
8484
let remainder: usize = size % max_buffer_size_bytes;
8585
let len: usize = (size - remainder) / max_buffer_size_bytes;
8686
let mut bufs: ArrayVec<DemiBuffer, DEMI_SGARRAY_MAXLEN> = ArrayVec::new();

0 commit comments

Comments
 (0)