1#![deny(warnings)]
4
5use std::io;
6use std::option::Option;
7use std::time::Duration;
8
9mod bindings;
10
11pub mod async_io;
12
13#[cfg(windows)]
14#[path = "wpcap.rs"]
15mod backend;
16
17#[cfg(windows)]
18pub mod wpcap;
19
20#[cfg(all(any(target_os = "linux", target_os = "android")))]
21#[path = "linux.rs"]
22mod backend;
23
24#[cfg(any(target_os = "linux", target_os = "android"))]
25pub mod linux;
26
27#[cfg(all(any(
28 target_os = "freebsd",
29 target_os = "openbsd",
30 target_os = "netbsd",
31 target_os = "illumos",
32 target_os = "solaris",
33 target_os = "macos",
34 target_os = "ios"
35)))]
36#[path = "bpf.rs"]
37mod backend;
38
39#[cfg(any(
40 target_os = "freebsd",
41 target_os = "netbsd",
42 target_os = "illumos",
43 target_os = "solaris",
44 target_os = "macos",
45 target_os = "ios"
46))]
47pub mod bpf;
48
49#[cfg(feature = "pcap")]
50pub mod pcap;
51
52pub type EtherType = u16;
54
55#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
57pub enum ChannelType {
58 Layer2,
60 Layer3(EtherType),
62}
63
64#[non_exhaustive]
66pub enum Channel {
67 Ethernet(Box<dyn RawSender>, Box<dyn RawReceiver>),
69}
70
71#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
73pub enum FanoutType {
74 HASH,
75 LB,
76 CPU,
77 ROLLOVER,
78 RND,
79 QM,
80 CBPF,
81 EBPF,
82}
83
84#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
86pub struct FanoutOption {
87 pub group_id: u16,
88 pub fanout_type: FanoutType,
89 pub defrag: bool,
90 pub rollover: bool,
91}
92
93#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
98pub struct Config {
99 pub write_buffer_size: usize,
101
102 pub read_buffer_size: usize,
104
105 pub read_timeout: Option<Duration>,
107
108 pub write_timeout: Option<Duration>,
110
111 pub channel_type: ChannelType,
114
115 pub bpf_fd_attempts: usize,
118
119 pub linux_fanout: Option<FanoutOption>,
120
121 pub promiscuous: bool,
122}
123
124impl Default for Config {
125 fn default() -> Config {
126 Config {
127 write_buffer_size: 4096,
128 read_buffer_size: 4096,
129 read_timeout: None,
130 write_timeout: None,
131 channel_type: ChannelType::Layer2,
132 bpf_fd_attempts: 1000,
133 linux_fanout: None,
134 promiscuous: true,
135 }
136 }
137}
138
139#[inline]
149pub fn channel(
150 network_interface: &nex_core::interface::Interface,
151 configuration: Config,
152) -> io::Result<Channel> {
153 backend::channel(network_interface, (&configuration).into())
154}
155
156pub trait RawSender: Send {
158 fn build_and_send(
165 &mut self,
166 num_packets: usize,
167 packet_size: usize,
168 func: &mut dyn FnMut(&mut [u8]),
169 ) -> Option<io::Result<()>>;
170
171 fn send(&mut self, packet: &[u8]) -> Option<io::Result<()>>;
176}
177
178pub trait RawReceiver: Send {
181 fn next(&mut self) -> io::Result<&[u8]>;
183}
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188
189 #[test]
190 fn config_default_values() {
191 let cfg = Config::default();
192 assert_eq!(cfg.write_buffer_size, 4096);
193 assert_eq!(cfg.read_buffer_size, 4096);
194 assert_eq!(cfg.read_timeout, None);
195 assert_eq!(cfg.write_timeout, None);
196 assert_eq!(cfg.channel_type, ChannelType::Layer2);
197 assert_eq!(cfg.bpf_fd_attempts, 1000);
198 assert!(cfg.linux_fanout.is_none());
199 assert!(cfg.promiscuous);
200 }
201}