Skip to content

Commit d8f882f

Browse files
committed
Do not terminate if single packet is too big to write
Instead, indicate in statistics that we were not able to write all packets.
1 parent f18ef83 commit d8f882f

File tree

2 files changed

+41
-5
lines changed

2 files changed

+41
-5
lines changed

src/output.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,28 @@ struct Interface(Pcap);
3838

3939
impl PacketWriter for Interface {
4040
fn write_raw(&mut self, buf: &[u8]) -> Result<usize> {
41-
Ok(self.0.inject(buf)?)
41+
match self.0.inject(buf) {
42+
Ok(ret) => Ok(ret),
43+
Err(err) => {
44+
tracing::warn!(?err, len = ?buf.len(), "error while trying to write");
45+
// we do not want to stop writing if we get error indicating that
46+
// packet was too large to write.
47+
if let luomu_libpcap::Error::PcapError(ref msg) = err {
48+
if msg.contains("Message too") && buf.len() > 1500 {
49+
// this is a stupid way to detect such errors, but there
50+
// is no other way currently, as the only thing we get
51+
// is error message from libpcap and it can contain at
52+
// least "Message too long" and "Message too large"
53+
// depending on the Linux distribution of choice.
54+
Ok(0)
55+
} else {
56+
Err(err.into())
57+
}
58+
} else {
59+
Err(err.into())
60+
}
61+
}
62+
}
4263
}
4364
}
4465

src/pipe.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ pub struct Stats {
1919
packets: u64,
2020
/// Number of bytes processed since start or last reset.
2121
bytes: u64,
22+
/// Number of packets which we were not able to send.
23+
invalid: u64,
2224
/// When packet processing has started.
2325
start: Instant,
2426
/// Interval for producing stats
@@ -36,18 +38,25 @@ impl Default for Stats {
3638
last_stat: Instant::now(),
3739
packets: Default::default(),
3840
bytes: Default::default(),
41+
invalid: Default::default(),
3942
sender: None,
4043
interval: None,
4144
}
4245
}
4346
}
4447

4548
impl Stats {
46-
/// Updates the statistics with a packet containing given number of bytes
49+
/// Updates the statistics with a packet containing given number of bytes.
50+
/// If `bytes` is 0, this is to indicate that packet was not sent and
51+
/// should increase the "invalid" packet count.
4752
///
4853
/// Sends summary of statistics if it is time to send them.
4954
fn update(&mut self, bytes: u64) {
50-
self.packets += 1;
55+
if bytes == 0 {
56+
self.invalid += 1
57+
} else {
58+
self.packets += 1;
59+
}
5160
self.bytes += bytes;
5261
if let Some(val) = self.interval {
5362
if self.last_stat.elapsed() > val {
@@ -71,9 +80,14 @@ impl Stats {
7180
let bps = (self.bytes as f64 * 8_f64) / elapsed.as_secs_f64();
7281
let mbps = (self.bytes as f64 / (1024 * 1024) as f64) / elapsed.as_secs_f64();
7382

83+
let packet_count = match self.invalid {
84+
0 => format!("{} packets", self.packets),
85+
_ => format!("{} packets ({} not sent)", self.packets, self.invalid),
86+
};
87+
7488
format!(
75-
"{} packets, {} bytes in {}ms / {:.3}pps, {:.3}bps ({:.3} MBps)",
76-
self.packets,
89+
"{}, {} bytes in {}ms / {:.3}pps, {:.3}bps ({:.3} MBps)",
90+
packet_count,
7791
self.bytes,
7892
elapsed.as_millis(),
7993
pps,
@@ -86,6 +100,7 @@ impl Stats {
86100
fn reset(&mut self) {
87101
self.bytes = 0;
88102
self.packets = 0;
103+
self.invalid = 0;
89104
self.start = Instant::now();
90105
}
91106

0 commit comments

Comments
 (0)