Newer
Older
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
use std::error::Error;
use std::net::UdpSocket;
use std::time::{SystemTime, UNIX_EPOCH};
use netem_evaluator::Message;
use netem_evaluator::NetemParameters;
const TIME_BETWEEN_MESSAGES_IN_MICRO_SECONDS: u64 = 10000;
const MESSAGES_TO_SEND: u32 = 1000;
fn main() -> Result<(), Box<dyn Error>> {
let socket = UdpSocket::bind("0.0.0.0:0")?;
let target = "10.0.0.1:6789";
socket.connect(target)?;
let mut id = 0;
// TEST GOAL: find out if there is a difference, between no netem, and netem with 0 delay
// There is a very small difference of 0.03ms on average
let mut netem_parameters = NetemParameters::new();
netem_evaluator::set_network_parameters(netem_parameters.clone());
send_messages_to_server(&socket, &mut id, MESSAGES_TO_SEND, Some(netem_parameters))?;
netem_evaluator::remove_qdiscs();
send_messages_to_server(&socket, &mut id, MESSAGES_TO_SEND, None)?;
netem_evaluator::create_qdiscs();
send_messages_to_server(
&socket,
&mut id,
MESSAGES_TO_SEND,
Some(NetemParameters::new()),
)?;
// TEST GOAL: find out how good the delay of netem works
// The delay is pretty accurate
netem_parameters = NetemParameters::new().with_delay(1);
netem_evaluator::set_network_parameters(netem_parameters.clone());
send_messages_to_server(&socket, &mut id, MESSAGES_TO_SEND, Some(netem_parameters))?;
netem_parameters = NetemParameters::new().with_delay(2);
netem_evaluator::set_network_parameters(netem_parameters.clone());
send_messages_to_server(&socket, &mut id, MESSAGES_TO_SEND, Some(netem_parameters))?;
netem_parameters = NetemParameters::new().with_delay(4);
netem_evaluator::set_network_parameters(netem_parameters.clone());
send_messages_to_server(&socket, &mut id, MESSAGES_TO_SEND, Some(netem_parameters))?;
netem_parameters = NetemParameters::new().with_delay(10);
netem_evaluator::set_network_parameters(netem_parameters.clone());
send_messages_to_server(&socket, &mut id, MESSAGES_TO_SEND, Some(netem_parameters))?;
netem_parameters = NetemParameters::new().with_delay(20);
netem_evaluator::set_network_parameters(netem_parameters.clone());
send_messages_to_server(&socket, &mut id, MESSAGES_TO_SEND, Some(netem_parameters))?;
netem_parameters = NetemParameters::new().with_delay(50);
netem_evaluator::set_network_parameters(netem_parameters.clone());
send_messages_to_server(&socket, &mut id, MESSAGES_TO_SEND, Some(netem_parameters))?;
netem_parameters = NetemParameters::new().with_delay(100);
netem_evaluator::set_network_parameters(netem_parameters.clone());
send_messages_to_server(&socket, &mut id, MESSAGES_TO_SEND, Some(netem_parameters))?;
Ok(())
}
fn send_messages_to_server(
socket: &UdpSocket,
id: &mut u128,
messages_to_send: u32,
netem_parameters: Option<NetemParameters>,
) -> Result<(), Box<dyn Error>> {
let mut buffer = [0u8; 1000];
for _ in 0..messages_to_send {
*id += 1;
// Get high-precision timestamp
// Using SystemTime for monotonic timestamps that are consistent across processes
let message = Message {
id: *id,
timestamp: SystemTime::now().duration_since(UNIX_EPOCH)?.as_nanos(),
netem_parameters: netem_parameters.clone(),
};
let mut cursor = std::io::Cursor::new(&mut buffer[..]);
bincode::serialize_into(&mut cursor, &message)?;
socket.send(&buffer)?;
println!("{message:?}");
// println!("{:02x?}", &buffer[0..100]);
buffer.fill(0);
std::thread::sleep(std::time::Duration::from_micros(
TIME_BETWEEN_MESSAGES_IN_MICRO_SECONDS,
));
}
std::thread::sleep(std::time::Duration::from_secs(1));
Ok(())
}