1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use std::{
net::{IpAddr, Ipv6Addr, SocketAddr},
sync::atomic::{AtomicUsize, Ordering},
time::{Duration, Instant},
};
use proto::{EcnCodepoint, Transmit};
use tracing::warn;
#[cfg(unix)]
mod cmsg;
#[cfg(unix)]
#[path = "unix.rs"]
mod imp;
#[cfg(not(unix))]
#[path = "fallback.rs"]
mod imp;
pub use imp::UdpSocket;
pub const BATCH_SIZE: usize = imp::BATCH_SIZE;
#[derive(Debug)]
pub struct UdpState {
max_gso_segments: AtomicUsize,
}
impl UdpState {
pub fn new() -> Self {
imp::udp_state()
}
#[inline]
pub fn max_gso_segments(&self) -> usize {
self.max_gso_segments.load(Ordering::Relaxed)
}
}
impl Default for UdpState {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Copy, Clone)]
pub struct RecvMeta {
pub addr: SocketAddr,
pub len: usize,
pub ecn: Option<EcnCodepoint>,
pub dst_ip: Option<IpAddr>,
}
impl Default for RecvMeta {
fn default() -> Self {
Self {
addr: SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0),
len: 0,
ecn: None,
dst_ip: None,
}
}
}
const IO_ERROR_LOG_INTERVAL: Duration = std::time::Duration::from_secs(60);
fn log_sendmsg_error(
last_send_error: &mut Instant,
err: impl core::fmt::Debug,
transmit: &Transmit,
) {
let now = Instant::now();
if now.saturating_duration_since(*last_send_error) > IO_ERROR_LOG_INTERVAL {
*last_send_error = now;
warn!(
"sendmsg error: {:?}, Transmit: {{ destination: {:?}, src_ip: {:?}, enc: {:?}, len: {:?}, segment_size: {:?} }}",
err, transmit.destination, transmit.src_ip, transmit.ecn, transmit.contents.len(), transmit.segment_size);
}
}