2018-04-17 19:46:50 -07:00
|
|
|
//! The `packet` module defines data structures and methods to pull data from the network.
|
2021-12-03 09:00:31 -08:00
|
|
|
use {
|
|
|
|
crate::{
|
|
|
|
recvmmsg::{recv_mmsg, NUM_RCVMMSGS},
|
|
|
|
socket::SocketAddrSpace,
|
|
|
|
},
|
|
|
|
solana_metrics::inc_new_counter_debug,
|
|
|
|
std::{io::Result, net::UdpSocket, time::Instant},
|
2021-07-16 10:41:01 -07:00
|
|
|
};
|
2021-12-03 09:00:31 -08:00
|
|
|
pub use {
|
|
|
|
solana_perf::packet::{
|
2022-05-23 20:15:20 -07:00
|
|
|
to_packet_batches, PacketBatch, PacketBatchRecycler, NUM_PACKETS, PACKETS_PER_BATCH,
|
2021-12-03 09:00:31 -08:00
|
|
|
},
|
|
|
|
solana_sdk::packet::{Meta, Packet, PACKET_DATA_SIZE},
|
2019-11-02 00:38:30 -07:00
|
|
|
};
|
2018-11-19 23:20:18 -08:00
|
|
|
|
2021-12-11 06:44:15 -08:00
|
|
|
pub fn recv_from(batch: &mut PacketBatch, socket: &UdpSocket, max_wait_ms: u64) -> Result<usize> {
|
2019-11-04 20:13:43 -08:00
|
|
|
let mut i = 0;
|
|
|
|
//DOCUMENTED SIDE-EFFECT
|
|
|
|
//Performance out of the IO without poll
|
|
|
|
// * block on the socket until it's readable
|
|
|
|
// * set the socket to non blocking
|
|
|
|
// * read until it fails
|
|
|
|
// * set it back to blocking before returning
|
|
|
|
socket.set_nonblocking(false)?;
|
|
|
|
trace!("receiving on {}", socket.local_addr().unwrap());
|
|
|
|
let start = Instant::now();
|
|
|
|
loop {
|
2022-05-23 13:30:15 -07:00
|
|
|
batch.resize(
|
2020-02-10 11:49:07 -08:00
|
|
|
std::cmp::min(i + NUM_RCVMMSGS, PACKETS_PER_BATCH),
|
|
|
|
Packet::default(),
|
|
|
|
);
|
2022-05-23 13:30:15 -07:00
|
|
|
match recv_mmsg(socket, &mut batch[i..]) {
|
2019-11-04 20:13:43 -08:00
|
|
|
Err(_) if i > 0 => {
|
2021-02-26 09:15:45 -08:00
|
|
|
if start.elapsed().as_millis() as u64 > max_wait_ms {
|
2019-11-04 20:13:43 -08:00
|
|
|
break;
|
2018-04-02 19:32:58 -07:00
|
|
|
}
|
2019-11-04 20:13:43 -08:00
|
|
|
}
|
|
|
|
Err(e) => {
|
|
|
|
trace!("recv_from err {:?}", e);
|
2020-01-02 19:50:43 -08:00
|
|
|
return Err(e);
|
2019-11-04 20:13:43 -08:00
|
|
|
}
|
2022-01-04 06:08:15 -08:00
|
|
|
Ok(npkts) => {
|
2019-11-04 20:13:43 -08:00
|
|
|
if i == 0 {
|
|
|
|
socket.set_nonblocking(true)?;
|
2018-04-02 19:32:58 -07:00
|
|
|
}
|
2019-11-04 20:13:43 -08:00
|
|
|
trace!("got {} packets", npkts);
|
|
|
|
i += npkts;
|
|
|
|
// Try to batch into big enough buffers
|
|
|
|
// will cause less re-shuffling later on.
|
2021-02-26 09:15:45 -08:00
|
|
|
if start.elapsed().as_millis() as u64 > max_wait_ms || i >= PACKETS_PER_BATCH {
|
2019-11-04 20:13:43 -08:00
|
|
|
break;
|
2018-04-02 19:32:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-05-23 13:30:15 -07:00
|
|
|
batch.truncate(i);
|
2019-11-04 20:13:43 -08:00
|
|
|
inc_new_counter_debug!("packets-recv_count", i);
|
|
|
|
Ok(i)
|
|
|
|
}
|
2019-04-17 14:14:57 -07:00
|
|
|
|
2021-07-23 08:25:03 -07:00
|
|
|
pub fn send_to(
|
2021-12-11 06:44:15 -08:00
|
|
|
batch: &PacketBatch,
|
2021-07-23 08:25:03 -07:00
|
|
|
socket: &UdpSocket,
|
|
|
|
socket_addr_space: &SocketAddrSpace,
|
|
|
|
) -> Result<()> {
|
2022-05-23 13:30:15 -07:00
|
|
|
for p in batch.iter() {
|
2022-12-06 03:54:49 -08:00
|
|
|
let addr = p.meta().socket_addr();
|
2021-07-23 08:25:03 -07:00
|
|
|
if socket_addr_space.check(&addr) {
|
2022-06-02 18:05:06 -07:00
|
|
|
if let Some(data) = p.data(..) {
|
2022-09-22 15:23:03 -07:00
|
|
|
socket.send_to(data, addr)?;
|
2022-06-02 18:05:06 -07:00
|
|
|
}
|
2021-07-16 10:41:01 -07:00
|
|
|
}
|
2018-04-02 19:32:58 -07:00
|
|
|
}
|
2019-11-04 20:13:43 -08:00
|
|
|
Ok(())
|
2018-04-02 19:32:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
2018-06-28 12:10:36 -07:00
|
|
|
mod tests {
|
2021-12-03 09:00:31 -08:00
|
|
|
use {
|
|
|
|
super::*,
|
|
|
|
std::{
|
|
|
|
io,
|
|
|
|
io::Write,
|
|
|
|
net::{SocketAddr, UdpSocket},
|
|
|
|
},
|
|
|
|
};
|
2019-01-10 12:34:48 -08:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_packets_set_addr() {
|
|
|
|
// test that the address is actually being updated
|
2020-03-17 23:30:23 -07:00
|
|
|
let send_addr: SocketAddr = "127.0.0.1:123".parse().unwrap();
|
2019-01-10 12:34:48 -08:00
|
|
|
let packets = vec![Packet::default()];
|
2021-12-11 06:44:15 -08:00
|
|
|
let mut packet_batch = PacketBatch::new(packets);
|
|
|
|
packet_batch.set_addr(&send_addr);
|
2022-12-06 03:54:49 -08:00
|
|
|
assert_eq!(packet_batch[0].meta().socket_addr(), send_addr);
|
2019-01-10 12:34:48 -08:00
|
|
|
}
|
2018-06-28 12:10:36 -07:00
|
|
|
|
2018-04-02 19:32:58 -07:00
|
|
|
#[test]
|
|
|
|
pub fn packet_send_recv() {
|
2019-04-17 14:14:57 -07:00
|
|
|
solana_logger::setup();
|
|
|
|
let recv_socket = UdpSocket::bind("127.0.0.1:0").expect("bind");
|
|
|
|
let addr = recv_socket.local_addr().unwrap();
|
|
|
|
let send_socket = UdpSocket::bind("127.0.0.1:0").expect("bind");
|
|
|
|
let saddr = send_socket.local_addr().unwrap();
|
|
|
|
|
2022-05-23 13:30:15 -07:00
|
|
|
let packet_batch_size = 10;
|
|
|
|
let mut batch = PacketBatch::with_capacity(packet_batch_size);
|
|
|
|
batch.resize(packet_batch_size, Packet::default());
|
2019-04-17 14:14:57 -07:00
|
|
|
|
2022-05-23 13:30:15 -07:00
|
|
|
for m in batch.iter_mut() {
|
2022-12-06 03:54:49 -08:00
|
|
|
m.meta_mut().set_socket_addr(&addr);
|
|
|
|
m.meta_mut().size = PACKET_DATA_SIZE;
|
2018-04-02 19:32:58 -07:00
|
|
|
}
|
2021-12-11 06:44:15 -08:00
|
|
|
send_to(&batch, &send_socket, &SocketAddrSpace::Unspecified).unwrap();
|
2019-04-17 14:14:57 -07:00
|
|
|
|
2022-12-06 03:54:49 -08:00
|
|
|
batch
|
|
|
|
.iter_mut()
|
|
|
|
.for_each(|pkt| *pkt.meta_mut() = Meta::default());
|
2021-12-11 06:44:15 -08:00
|
|
|
let recvd = recv_from(&mut batch, &recv_socket, 1).unwrap();
|
2019-04-17 14:14:57 -07:00
|
|
|
|
2022-05-23 13:30:15 -07:00
|
|
|
assert_eq!(recvd, batch.len());
|
2019-04-17 14:14:57 -07:00
|
|
|
|
2022-05-23 13:30:15 -07:00
|
|
|
for m in batch.iter() {
|
2022-12-06 03:54:49 -08:00
|
|
|
assert_eq!(m.meta().size, PACKET_DATA_SIZE);
|
|
|
|
assert_eq!(m.meta().socket_addr(), saddr);
|
2018-04-02 19:32:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
pub fn debug_trait() {
|
|
|
|
write!(io::sink(), "{:?}", Packet::default()).unwrap();
|
2021-12-11 06:44:15 -08:00
|
|
|
write!(io::sink(), "{:?}", PacketBatch::default()).unwrap();
|
2019-04-14 17:30:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_packet_partial_eq() {
|
2019-05-29 10:08:35 -07:00
|
|
|
let mut p1 = Packet::default();
|
2019-04-14 17:30:08 -07:00
|
|
|
let mut p2 = Packet::default();
|
|
|
|
|
2022-12-06 03:54:49 -08:00
|
|
|
p1.meta_mut().size = 1;
|
2022-05-25 09:52:54 -07:00
|
|
|
p1.buffer_mut()[0] = 0;
|
2019-05-29 10:08:35 -07:00
|
|
|
|
2022-12-06 03:54:49 -08:00
|
|
|
p2.meta_mut().size = 1;
|
2022-05-25 09:52:54 -07:00
|
|
|
p2.buffer_mut()[0] = 0;
|
2019-05-29 10:08:35 -07:00
|
|
|
|
2019-04-14 17:30:08 -07:00
|
|
|
assert!(p1 == p2);
|
2019-05-29 10:08:35 -07:00
|
|
|
|
2022-05-25 09:52:54 -07:00
|
|
|
p2.buffer_mut()[0] = 4;
|
2019-04-14 17:30:08 -07:00
|
|
|
assert!(p1 != p2);
|
|
|
|
}
|
2020-02-10 11:49:07 -08:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_packet_resize() {
|
|
|
|
solana_logger::setup();
|
|
|
|
let recv_socket = UdpSocket::bind("127.0.0.1:0").expect("bind");
|
|
|
|
let addr = recv_socket.local_addr().unwrap();
|
|
|
|
let send_socket = UdpSocket::bind("127.0.0.1:0").expect("bind");
|
2022-05-23 13:30:15 -07:00
|
|
|
let mut batch = PacketBatch::with_capacity(PACKETS_PER_BATCH);
|
|
|
|
batch.resize(PACKETS_PER_BATCH, Packet::default());
|
2020-02-10 11:49:07 -08:00
|
|
|
|
|
|
|
// Should only get PACKETS_PER_BATCH packets per iteration even
|
|
|
|
// if a lot more were sent, and regardless of packet size
|
|
|
|
for _ in 0..2 * PACKETS_PER_BATCH {
|
2022-05-23 13:30:15 -07:00
|
|
|
let batch_size = 1;
|
|
|
|
let mut batch = PacketBatch::with_capacity(batch_size);
|
|
|
|
batch.resize(batch_size, Packet::default());
|
|
|
|
for p in batch.iter_mut() {
|
2022-12-06 03:54:49 -08:00
|
|
|
p.meta_mut().set_socket_addr(&addr);
|
|
|
|
p.meta_mut().size = 1;
|
2020-02-10 11:49:07 -08:00
|
|
|
}
|
2021-12-11 06:44:15 -08:00
|
|
|
send_to(&batch, &send_socket, &SocketAddrSpace::Unspecified).unwrap();
|
2020-02-10 11:49:07 -08:00
|
|
|
}
|
|
|
|
|
2021-12-11 06:44:15 -08:00
|
|
|
let recvd = recv_from(&mut batch, &recv_socket, 100).unwrap();
|
2020-02-10 11:49:07 -08:00
|
|
|
|
|
|
|
// Check we only got PACKETS_PER_BATCH packets
|
|
|
|
assert_eq!(recvd, PACKETS_PER_BATCH);
|
2022-05-23 13:30:15 -07:00
|
|
|
assert_eq!(batch.capacity(), PACKETS_PER_BATCH);
|
2020-02-10 11:49:07 -08:00
|
|
|
}
|
2018-04-02 19:32:58 -07:00
|
|
|
}
|