1use std::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell};
4use std::collections::BTreeMap;
5use std::ffi::{CStr, CString, OsString};
6use std::net::{Ipv4Addr, SocketAddrV4};
7use std::ops::{Deref, DerefMut};
8use std::os::unix::prelude::OsStringExt;
9use std::path::{Path, PathBuf};
10use std::sync::{Arc, Mutex};
11
12use asm_util::tsc::Tsc;
13use atomic_refcell::AtomicRefCell;
14use linux_api::signal::{Signal, siginfo_t};
15use log::{debug, trace};
16use logger::LogLevel;
17use once_cell::unsync::OnceCell;
18use rand::SeedableRng;
19use rand_xoshiro::Xoshiro256PlusPlus;
20use shadow_shim_helper_rs::HostId;
21use shadow_shim_helper_rs::emulated_time::EmulatedTime;
22use shadow_shim_helper_rs::explicit_drop::ExplicitDropper;
23use shadow_shim_helper_rs::rootedcell::Root;
24use shadow_shim_helper_rs::rootedcell::cell::RootedCell;
25use shadow_shim_helper_rs::rootedcell::rc::RootedRc;
26use shadow_shim_helper_rs::rootedcell::refcell::RootedRefCell;
27use shadow_shim_helper_rs::shim_shmem::{HostShmem, HostShmemProtected, ManagerShmem};
28use shadow_shim_helper_rs::simulation_time::SimulationTime;
29use shadow_shmem::allocator::ShMemBlock;
30use vasi_sync::scmutex::SelfContainedMutexGuard;
31
32use crate::core::configuration::{ProcessFinalState, QDiscMode};
33use crate::core::sim_config::PcapConfig;
34use crate::core::work::event::{Event, EventData};
35use crate::core::work::event_queue::EventQueue;
36use crate::core::work::task::TaskRef;
37use crate::core::worker::Worker;
38use crate::cshadow;
39use crate::host::descriptor::socket::abstract_unix_ns::AbstractUnixNamespace;
40use crate::host::descriptor::socket::inet::InetSocket;
41use crate::host::fcntl_lock_table::FcntlLockTable;
42use crate::host::futex_table::FutexTable;
43use crate::host::network::interface::{FifoPacketPriority, NetworkInterface, PcapOptions};
44use crate::host::network::namespace::NetworkNamespace;
45use crate::host::process::Process;
46use crate::host::thread::{Thread, ThreadId};
47use crate::network::PacketDevice;
48use crate::network::relay::{RateLimit, Relay};
49use crate::network::router::Router;
50use crate::utility;
51#[cfg(feature = "perf_timers")]
52use crate::utility::perf_timer::PerfTimer;
53
54pub struct HostParameters {
55 pub id: HostId,
56 pub node_seed: u64,
57 pub hostname: CString,
60 pub node_id: u32,
61 pub ip_addr: libc::in_addr_t,
62 pub sim_end_time: EmulatedTime,
63 pub requested_bw_down_bits: u64,
64 pub requested_bw_up_bits: u64,
65 pub cpu_frequency: u64,
66 pub cpu_threshold: Option<SimulationTime>,
67 pub cpu_precision: Option<SimulationTime>,
68 pub log_level: LogLevel,
69 pub pcap_config: Option<PcapConfig>,
70 pub qdisc: QDiscMode,
71 pub init_sock_recv_buf_size: u64,
72 pub autotune_recv_buf: bool,
73 pub init_sock_send_buf_size: u64,
74 pub autotune_send_buf: bool,
75 pub native_tsc_frequency: u64,
76 pub model_unblocked_syscall_latency: bool,
77 pub max_unapplied_cpu_latency: SimulationTime,
78 pub unblocked_syscall_latency: SimulationTime,
79 pub unblocked_vdso_latency: SimulationTime,
80 pub strace_logging_options: Option<FmtOptions>,
81 pub shim_log_level: LogLevel,
82 pub use_new_tcp: bool,
83 pub use_syscall_counters: bool,
84}
85
86use super::cpu::Cpu;
87use super::process::ProcessId;
88use super::syscall::formatter::FmtOptions;
89
90#[derive(Debug, Clone)]
92pub struct HostInfo {
93 pub id: HostId,
94 pub name: String,
95 pub default_ip: Ipv4Addr,
96 pub log_level: Option<log::LevelFilter>,
97}
98
99pub struct Host {
101 info: OnceCell<Arc<HostInfo>>,
108
109 root: Root,
114
115 event_queue: Arc<Mutex<EventQueue>>,
116
117 random: RefCell<Xoshiro256PlusPlus>,
118
119 router: RefCell<Router>,
123
124 relay_inet_out: Arc<Relay>,
126 relay_inet_in: Arc<Relay>,
128 relay_loopback: Arc<Relay>,
130
131 futex_table: RefCell<FutexTable>,
133
134 fcntl_lock_table: RefCell<FcntlLockTable>,
136
137 #[cfg(feature = "perf_timers")]
138 execution_timer: RefCell<PerfTimer>,
139
140 pub params: HostParameters,
141
142 cpu: RefCell<Cpu>,
143
144 net_ns: NetworkNamespace,
145
146 data_dir_path: PathBuf,
152 data_dir_path_cstring: CString,
153
154 thread_id_counter: Cell<libc::pid_t>,
156 event_id_counter: Cell<u64>,
157 packet_id_counter: Cell<u64>,
158
159 determinism_sequence_counter: Cell<u64>,
161
162 packet_priority_counter: Cell<FifoPacketPriority>,
164
165 processes: RefCell<BTreeMap<ProcessId, RootedRc<RootedRefCell<Process>>>>,
167
168 tsc: Tsc,
169 shim_shmem_lock:
180 RefCell<Option<UnsafeCell<SelfContainedMutexGuard<'static, HostShmemProtected>>>>,
181 shim_shmem: UnsafeCell<ShMemBlock<'static, HostShmem>>,
193
194 in_notify_socket_has_packets: RootedCell<bool>,
195
196 preload_paths: Arc<Vec<PathBuf>>,
198}
199
200impl crate::utility::IsSend for Host {}
202
203impl std::fmt::Debug for Host {
205 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
206 f.debug_struct("Host")
207 .field("info", &self.info)
208 .finish_non_exhaustive()
209 }
210}
211
212impl Host {
213 pub fn new(
214 params: HostParameters,
215 host_root_path: &Path,
216 raw_cpu_freq_khz: u64,
217 manager_shmem: &ShMemBlock<ManagerShmem>,
218 preload_paths: Arc<Vec<PathBuf>>,
219 ) -> Self {
220 #[cfg(feature = "perf_timers")]
221 let execution_timer = RefCell::new(PerfTimer::new_started());
222
223 let root = Root::new();
224 let random = RefCell::new(Xoshiro256PlusPlus::seed_from_u64(params.node_seed));
225 let cpu = RefCell::new(Cpu::new(
226 params.cpu_frequency,
227 raw_cpu_freq_khz,
228 params.cpu_threshold,
229 params.cpu_precision,
230 ));
231 let data_dir_path = Self::make_data_dir_path(¶ms.hostname, host_root_path);
232 let data_dir_path_cstring = utility::pathbuf_to_nul_term_cstring(data_dir_path.clone());
233
234 let host_shmem = HostShmem::new(
235 params.id,
236 params.model_unblocked_syscall_latency,
237 params.max_unapplied_cpu_latency,
238 params.unblocked_syscall_latency,
239 params.unblocked_vdso_latency,
240 nix::unistd::getpid().as_raw(),
241 params.native_tsc_frequency,
242 params.shim_log_level,
243 manager_shmem,
244 );
245 let shim_shmem = UnsafeCell::new(shadow_shmem::allocator::shmalloc(host_shmem));
246
247 let thread_id_counter = Cell::new(1000);
249 let event_id_counter = Cell::new(0);
250 let packet_id_counter = Cell::new(0);
251 let determinism_sequence_counter = Cell::new(0);
252 let packet_priority_counter = Cell::new(1);
254 let tsc = Tsc::new(params.native_tsc_frequency);
255
256 std::fs::create_dir_all(&data_dir_path).unwrap();
257
258 let public_ip: Ipv4Addr = u32::from_be(params.ip_addr).into();
262
263 let pcap_options = params.pcap_config.as_ref().map(|x| PcapOptions {
264 path: data_dir_path.clone(),
265 capture_size_bytes: x.capture_size.try_into().unwrap(),
266 });
267
268 let net_ns = NetworkNamespace::new(public_ip, pcap_options, params.qdisc);
269
270 let router = Router::new(Ipv4Addr::UNSPECIFIED);
274 let relay_inet_out = Relay::new(
275 RateLimit::BytesPerSecond(params.requested_bw_up_bits / 8),
276 net_ns.internet.borrow().get_address(),
277 );
278 let relay_inet_in = Relay::new(
279 RateLimit::BytesPerSecond(params.requested_bw_down_bits / 8),
280 router.get_address(),
281 );
282 let relay_loopback = Relay::new(
283 RateLimit::Unlimited,
284 net_ns.localhost.borrow().get_address(),
285 );
286
287 let in_notify_socket_has_packets = RootedCell::new(&root, false);
288
289 let res = Self {
290 info: OnceCell::new(),
291 root,
292 event_queue: Arc::new(Mutex::new(EventQueue::new())),
293 params,
294 router: RefCell::new(router),
295 relay_inet_out: Arc::new(relay_inet_out),
296 relay_inet_in: Arc::new(relay_inet_in),
297 relay_loopback: Arc::new(relay_loopback),
298 futex_table: RefCell::new(FutexTable::new()),
299 fcntl_lock_table: RefCell::new(FcntlLockTable::new()),
300 random,
301 shim_shmem,
302 shim_shmem_lock: RefCell::new(None),
303 cpu,
304 net_ns,
305 data_dir_path,
306 data_dir_path_cstring,
307 thread_id_counter,
308 event_id_counter,
309 packet_id_counter,
310 packet_priority_counter,
311 determinism_sequence_counter,
312 tsc,
313 processes: RefCell::new(BTreeMap::new()),
314 #[cfg(feature = "perf_timers")]
315 execution_timer,
316 in_notify_socket_has_packets,
317 preload_paths,
318 };
319
320 res.stop_execution_timer();
321
322 debug!(
323 concat!(
324 "Setup host id '{:?}'",
325 " name '{name}'",
326 " with seed {seed},",
327 " {bw_up_kiBps} bwUpKiBps,",
328 " {bw_down_kiBps} bwDownKiBps,",
329 " {init_sock_send_buf_size} initSockSendBufSize,",
330 " {init_sock_recv_buf_size} initSockRecvBufSize, ",
331 " {cpu_frequency:?} cpuFrequency, ",
332 " {cpu_threshold:?} cpuThreshold, ",
333 " {cpu_precision:?} cpuPrecision"
334 ),
335 res.id(),
336 name = res.info().name,
337 seed = res.params.node_seed,
338 bw_up_kiBps = res.bw_up_kiBps(),
339 bw_down_kiBps = res.bw_down_kiBps(),
340 init_sock_send_buf_size = res.params.init_sock_send_buf_size,
341 init_sock_recv_buf_size = res.params.init_sock_recv_buf_size,
342 cpu_frequency = res.params.cpu_frequency,
343 cpu_threshold = res.params.cpu_threshold,
344 cpu_precision = res.params.cpu_precision,
345 );
346
347 res
348 }
349
350 pub fn root(&self) -> &Root {
351 &self.root
352 }
353
354 fn make_data_dir_path(hostname: &CStr, host_root_path: &Path) -> PathBuf {
355 let hostname: OsString = { OsString::from_vec(hostname.to_bytes().to_vec()) };
356
357 let mut data_dir_path = PathBuf::new();
358 data_dir_path.push(host_root_path);
359 data_dir_path.push(&hostname);
360 data_dir_path
361 }
362
363 pub fn data_dir_path(&self) -> &Path {
364 &self.data_dir_path
365 }
366
367 pub fn add_application(
368 &self,
369 start_time: SimulationTime,
370 shutdown_time: Option<SimulationTime>,
371 shutdown_signal: nix::sys::signal::Signal,
372 plugin_name: CString,
373 plugin_path: CString,
374 argv: Vec<CString>,
375 envv: Vec<CString>,
376 pause_for_debugging: bool,
377 expected_final_state: ProcessFinalState,
378 ) {
379 debug_assert!(shutdown_time.is_none() || shutdown_time.unwrap() > start_time);
380
381 let task = TaskRef::new(move |host| {
383 let envv = envv.clone();
387 let argv = argv.clone();
388
389 let process = Process::spawn(
390 host,
391 plugin_name.clone(),
392 &plugin_path,
393 argv,
394 envv,
395 pause_for_debugging,
396 host.params.strace_logging_options,
397 expected_final_state,
398 )
399 .unwrap_or_else(|e| panic!("Failed to initialize application {plugin_name:?}: {e:?}"));
400 let (process_id, thread_id) = {
401 let process = process.borrow(host.root());
402 (process.id(), process.thread_group_leader_id())
403 };
404 host.processes.borrow_mut().insert(process_id, process);
405
406 if let Some(shutdown_time) = shutdown_time {
407 let task = TaskRef::new(move |host| {
408 let Some(process) = host.process_borrow(process_id) else {
409 debug!(
410 "Can't send shutdown signal to process {process_id}; it no longer exists"
411 );
412 return;
413 };
414 let process = process.borrow(host.root());
415 let siginfo = siginfo_t::new_for_kill(
416 Signal::try_from(shutdown_signal as i32).unwrap(),
417 1,
418 0,
419 );
420 process.signal(host, None, &siginfo);
421 });
422 host.schedule_task_at_emulated_time(
423 task,
424 EmulatedTime::SIMULATION_START + shutdown_time,
425 );
426 }
427
428 host.resume(process_id, thread_id);
429 });
430 self.schedule_task_at_emulated_time(task, EmulatedTime::SIMULATION_START + start_time);
431 }
432
433 pub fn add_and_schedule_forked_process(
434 &self,
435 host: &Host,
436 process: RootedRc<RootedRefCell<Process>>,
437 ) {
438 let (process_id, thread_id) = {
439 let process = process.borrow(&self.root);
440 (process.id(), process.thread_group_leader_id())
441 };
442 host.processes.borrow_mut().insert(process_id, process);
443 let task = TaskRef::new(move |host| {
445 host.resume(process_id, thread_id);
446 });
447 self.schedule_task_with_delay(task, SimulationTime::ZERO);
448 }
449
450 pub fn resume(&self, pid: ProcessId, tid: ThreadId) {
451 let Some(processrc) = self
452 .process_borrow(pid)
453 .map(|p| RootedRc::clone(&p, &self.root))
454 else {
455 trace!("{pid:?} doesn't exist");
456 return;
457 };
458 let processrc = ExplicitDropper::new(processrc, |p| {
459 p.explicit_drop_recursive(&self.root, self);
460 });
461 let died;
462 let is_orphan;
463 {
464 Worker::set_active_process(&processrc);
465 let process = processrc.borrow(self.root());
466 process.resume(self, tid);
467 Worker::clear_active_process();
468 let zombie_state = process.borrow_as_zombie();
469 if let Some(zombie) = zombie_state {
470 died = true;
471 is_orphan = zombie.reaper(self).is_none();
472 } else {
473 died = false;
474 is_orphan = false;
475 }
476 };
477
478 if !died {
479 return;
480 }
481
482 let child_pids: Vec<_> = self
483 .processes
484 .borrow()
485 .iter()
486 .filter_map(|(other_pid, processrc)| {
487 let process = processrc.borrow(&self.root);
488 if process.parent_id() != pid {
489 return None;
491 }
492 Some(*other_pid)
493 })
494 .collect();
495
496 let mut orphaned_zombie_pids: Vec<ProcessId> = Vec::new();
502 for child_pid in child_pids {
503 let parent_death_signal = {
504 let Some(processrc) = self.process_borrow(child_pid) else {
505 continue;
506 };
507 let process = processrc.borrow(&self.root);
508 process.parent_death_signal()
509 };
510
511 if let Some(signal) = parent_death_signal {
512 let siginfo = siginfo_t::new_for_kill(signal, pid.into(), 0);
513 let Some(processrc) = self.process_borrow(child_pid) else {
514 continue;
515 };
516 let process = processrc.borrow(&self.root);
517 process.signal(self, None, &siginfo);
518 }
519
520 let is_zombie = {
521 let Some(processrc) = self.process_borrow(child_pid) else {
522 continue;
523 };
524 let process = processrc.borrow(&self.root);
525 process.set_parent_id(ProcessId::INIT);
526 process.borrow_as_zombie().is_some()
527 };
528 if is_zombie {
529 orphaned_zombie_pids.push(child_pid);
530 }
531 }
532
533 debug_assert!(died);
535 if is_orphan {
536 orphaned_zombie_pids.push(pid);
537 }
538
539 let mut processes = self.processes.borrow_mut();
541 for pid in orphaned_zombie_pids {
542 trace!("Dropping orphan zombie process {pid:?}");
543 let processrc = processes.remove(&pid).unwrap();
544 RootedRc::explicit_drop_recursive(processrc, &self.root, self);
545 }
546 }
547
548 #[track_caller]
549 pub fn process_borrow(
550 &self,
551 id: ProcessId,
552 ) -> Option<impl Deref<Target = RootedRc<RootedRefCell<Process>>> + '_> {
553 Ref::filter_map(self.processes.borrow(), |processes| processes.get(&id)).ok()
554 }
555
556 #[track_caller]
558 pub fn process_remove(&self, id: ProcessId) -> Option<RootedRc<RootedRefCell<Process>>> {
559 self.processes.borrow_mut().remove(&id)
560 }
561
562 #[track_caller]
571 pub fn processes_borrow(
572 &self,
573 ) -> impl Deref<Target = BTreeMap<ProcessId, RootedRc<RootedRefCell<Process>>>> + '_ {
574 self.processes.borrow()
575 }
576
577 pub fn cpu_borrow(&self) -> impl Deref<Target = Cpu> + '_ {
578 self.cpu.borrow()
579 }
580
581 pub fn cpu_borrow_mut(&self) -> impl DerefMut<Target = Cpu> + '_ {
582 self.cpu.borrow_mut()
583 }
584
585 pub fn info(&self) -> &Arc<HostInfo> {
590 self.info.get_or_init(|| {
591 Arc::new(HostInfo {
592 id: self.id(),
593 name: self.params.hostname.to_str().unwrap().to_owned(),
594 default_ip: self.default_ip(),
595 log_level: self.log_level(),
596 })
597 })
598 }
599
600 pub fn id(&self) -> HostId {
601 self.params.id
602 }
603
604 pub fn name(&self) -> &str {
605 &self.info().name
606 }
607
608 pub fn default_ip(&self) -> Ipv4Addr {
609 self.net_ns.default_ip
610 }
611
612 pub fn abstract_unix_namespace(
613 &self,
614 ) -> impl Deref<Target = Arc<AtomicRefCell<AbstractUnixNamespace>>> + '_ {
615 &self.net_ns.unix
616 }
617
618 pub fn log_level(&self) -> Option<log::LevelFilter> {
619 let level = self.params.log_level;
620 log_c2rust::c_to_rust_log_level(level).map(|l| l.to_level_filter())
621 }
622
623 #[track_caller]
624 pub fn upstream_router_borrow_mut(&self) -> impl DerefMut<Target = Router> + '_ {
625 self.router.borrow_mut()
626 }
627
628 #[track_caller]
629 pub fn network_namespace_borrow(&self) -> impl Deref<Target = NetworkNamespace> + '_ {
630 &self.net_ns
631 }
632
633 #[track_caller]
634 pub fn futextable_borrow(&self) -> impl Deref<Target = FutexTable> + '_ {
635 self.futex_table.borrow()
636 }
637
638 #[track_caller]
639 pub fn futextable_borrow_mut(&self) -> impl DerefMut<Target = FutexTable> + '_ {
640 self.futex_table.borrow_mut()
641 }
642
643 #[track_caller]
644 pub fn fcntl_lock_table_borrow(&self) -> impl Deref<Target = FcntlLockTable> + '_ {
645 self.fcntl_lock_table.borrow()
646 }
647
648 #[track_caller]
649 pub fn fcntl_lock_table_borrow_mut(&self) -> impl DerefMut<Target = FcntlLockTable> + '_ {
650 self.fcntl_lock_table.borrow_mut()
651 }
652
653 #[allow(non_snake_case)]
654 pub fn bw_up_kiBps(&self) -> u64 {
655 self.params.requested_bw_up_bits / (8 * 1024)
656 }
657
658 #[allow(non_snake_case)]
659 pub fn bw_down_kiBps(&self) -> u64 {
660 self.params.requested_bw_down_bits / (8 * 1024)
661 }
662
663 pub fn interface_borrow_mut(
667 &self,
668 addr: Ipv4Addr,
669 ) -> Option<impl DerefMut<Target = NetworkInterface> + '_> {
670 self.net_ns.interface_borrow_mut(addr)
671 }
672
673 pub fn interface_borrow(
677 &self,
678 addr: Ipv4Addr,
679 ) -> Option<impl Deref<Target = NetworkInterface> + '_> {
680 self.net_ns.interface_borrow(addr)
681 }
682
683 #[track_caller]
684 pub fn random_mut(&self) -> impl DerefMut<Target = Xoshiro256PlusPlus> + '_ {
685 self.random.borrow_mut()
686 }
687
688 pub fn get_new_event_id(&self) -> u64 {
689 let res = self.event_id_counter.get();
690 self.event_id_counter.set(res + 1);
691 res
692 }
693
694 pub fn get_new_thread_id(&self) -> ThreadId {
695 let res = self.thread_id_counter.get();
696 self.thread_id_counter.set(res + 1);
697 res.try_into().unwrap()
698 }
699
700 pub fn get_new_packet_id(&self) -> u64 {
701 let res = self.packet_id_counter.get();
702 self.packet_id_counter.set(res + 1);
703 res
704 }
705
706 pub fn get_next_deterministic_sequence_value(&self) -> u64 {
707 let res = self.determinism_sequence_counter.get();
708 self.determinism_sequence_counter.set(res + 1);
709 res
710 }
711
712 pub fn get_next_packet_priority(&self) -> FifoPacketPriority {
713 let res = self.packet_priority_counter.get();
714 self.packet_priority_counter
715 .set(res.checked_add(1).unwrap());
716 res
717 }
718
719 pub fn continue_execution_timer(&self) {
720 #[cfg(feature = "perf_timers")]
721 self.execution_timer.borrow_mut().start();
722 }
723
724 pub fn stop_execution_timer(&self) {
725 #[cfg(feature = "perf_timers")]
726 self.execution_timer.borrow_mut().stop();
727 }
728
729 pub fn schedule_task_at_emulated_time(&self, task: TaskRef, t: EmulatedTime) -> bool {
730 let event = Event::new_local(task, t, self);
731 self.push_local_event(event)
732 }
733
734 pub fn schedule_task_with_delay(&self, task: TaskRef, t: SimulationTime) -> bool {
735 self.schedule_task_at_emulated_time(task, Worker::current_time().unwrap() + t)
736 }
737
738 pub fn event_queue(&self) -> &Arc<Mutex<EventQueue>> {
739 &self.event_queue
740 }
741
742 pub fn push_local_event(&self, event: Event) -> bool {
743 if event.time() >= self.params.sim_end_time {
744 return false;
745 }
746 self.event_queue.lock().unwrap().push(event);
747 true
748 }
749
750 pub fn shutdown(&self) {
752 self.continue_execution_timer();
753
754 debug!("shutting down host {}", self.name());
755
756 self.net_ns.cleanup();
758
759 assert!(self.processes.borrow().is_empty());
760
761 self.stop_execution_timer();
762 #[cfg(feature = "perf_timers")]
763 debug!(
764 "host '{}' has been shut down, total execution time was {:?}",
765 self.name(),
766 self.execution_timer.borrow().elapsed()
767 );
768 }
769
770 pub fn free_all_applications(&self) {
771 trace!("start freeing applications for host '{}'", self.name());
772 let processes = std::mem::take(&mut *self.processes.borrow_mut());
773 for (_id, processrc) in processes.into_iter() {
774 let processrc = ExplicitDropper::new(processrc, |p| {
775 p.explicit_drop_recursive(self.root(), self);
776 });
777 Worker::set_active_process(&processrc);
778 let process = processrc.borrow(self.root());
779 process.stop(self);
780 Worker::clear_active_process();
781 process.set_parent_id(ProcessId::INIT);
784 }
785 trace!("done freeing application for host '{}'", self.name());
786 }
787
788 pub fn execute(&self, until: EmulatedTime) {
789 loop {
790 let mut event = {
791 let mut event_queue = self.event_queue.lock().unwrap();
792 match event_queue.next_event_time() {
793 Some(t) if t < until => {}
794 _ => break,
795 };
796 event_queue.pop().unwrap()
797 };
798
799 {
800 let mut cpu = self.cpu.borrow_mut();
801 cpu.update_time(event.time());
802 let cpu_delay = cpu.delay();
803 if cpu_delay > SimulationTime::ZERO {
804 trace!("event blocked on CPU, rescheduled for {cpu_delay:?} from now");
805
806 event.set_time(event.time() + cpu_delay);
808 self.push_local_event(event);
809
810 continue;
812 }
813 }
814
815 Worker::set_current_time(event.time());
817 self.continue_execution_timer();
818 match event.data() {
819 EventData::Packet(data) => {
820 self.upstream_router_borrow_mut()
821 .route_incoming_packet(data.into());
822 self.notify_router_has_packets();
823 }
824 EventData::Local(data) => TaskRef::from(data).execute(self),
825 }
826 self.stop_execution_timer();
827 Worker::clear_current_time();
828 }
829 }
830
831 pub fn next_event_time(&self) -> Option<EmulatedTime> {
832 self.event_queue.lock().unwrap().next_event_time()
833 }
834
835 pub fn shim_shmem(&self) -> &ShMemBlock<'static, HostShmem> {
841 unsafe { &*self.shim_shmem.get() }
842 }
843
844 pub fn thread_cloned_rc(
847 &self,
848 virtual_tid: ThreadId,
849 ) -> Option<RootedRc<RootedRefCell<Thread>>> {
850 for process in self.processes.borrow().values() {
851 let process = process.borrow(self.root());
852 if let Some(thread) = process.thread_borrow(virtual_tid) {
853 return Some(RootedRc::clone(&*thread, self.root()));
854 };
855 }
856
857 None
858 }
859
860 pub fn has_thread(&self, virtual_tid: ThreadId) -> bool {
862 for process in self.processes.borrow().values() {
863 let process = process.borrow(self.root());
864 if process.thread_borrow(virtual_tid).is_some() {
865 return true;
866 }
867 }
868
869 false
870 }
871
872 pub fn lock_shmem(&self) {
878 let shim_shmem: &'static ShMemBlock<HostShmem> =
890 unsafe { self.shim_shmem.get().as_ref().unwrap() };
891 let lock = shim_shmem.protected().lock();
892 let prev = self
893 .shim_shmem_lock
894 .borrow_mut()
895 .replace(UnsafeCell::new(lock));
896 assert!(prev.is_none());
897 }
898
899 pub fn unlock_shmem(&self) {
902 let prev = self.shim_shmem_lock.borrow_mut().take();
903 assert!(prev.is_some());
904 }
905
906 pub fn shim_shmem_lock_borrow(&self) -> Option<impl Deref<Target = HostShmemProtected> + '_> {
907 Ref::filter_map(self.shim_shmem_lock.borrow(), |l| {
908 l.as_ref().map(|l| {
909 let guard = unsafe { &*l.get() };
913 guard.deref()
914 })
915 })
916 .ok()
917 }
918
919 pub fn shim_shmem_lock_borrow_mut(
920 &self,
921 ) -> Option<impl DerefMut<Target = HostShmemProtected> + '_> {
922 RefMut::filter_map(self.shim_shmem_lock.borrow_mut(), |l| {
923 l.as_ref().map(|l| {
924 let guard = unsafe { &mut *l.get() };
928 guard.deref_mut()
929 })
930 })
931 .ok()
932 }
933
934 pub fn tsc(&self) -> &Tsc {
937 &self.tsc
938 }
939
940 pub fn get_packet_device(&self, address: Ipv4Addr) -> Ref<'_, dyn PacketDevice> {
946 if address == Ipv4Addr::LOCALHOST {
947 self.net_ns.localhost.borrow()
948 } else if address == self.default_ip() {
949 self.net_ns.internet.borrow()
950 } else {
951 self.router.borrow()
952 }
953 }
954
955 pub fn notify_router_has_packets(&self) {
958 self.relay_inet_in.notify(self);
959 }
960
961 pub fn notify_socket_has_packets(&self, addr: Ipv4Addr, socket: &InetSocket) {
969 if self.in_notify_socket_has_packets.replace(&self.root, true) {
970 panic!("Recursively calling host.notify_socket_has_packets()");
971 }
972
973 if let Some(iface) = self.interface_borrow(addr) {
974 iface.add_data_source(socket);
975 match addr {
976 Ipv4Addr::LOCALHOST => self.relay_loopback.notify(self),
977 _ => self.relay_inet_out.notify(self),
978 };
979 }
980
981 self.in_notify_socket_has_packets.set(&self.root, false);
982 }
983
984 pub fn process_session_id_of_group_id(&self, group_id: ProcessId) -> Option<ProcessId> {
986 let processes = self.processes.borrow();
987 for processrc in processes.values() {
988 let process = processrc.borrow(&self.root);
989 if process.group_id() == group_id {
990 return Some(process.session_id());
991 }
992 }
993 None
994 }
995
996 pub fn preload_paths(&self) -> &[PathBuf] {
998 &self.preload_paths
999 }
1000}
1001
1002impl Drop for Host {
1003 fn drop(&mut self) {
1004 assert!(self.shim_shmem_lock.borrow().is_none());
1008 }
1009}
1010
1011mod export {
1012 use std::{os::raw::c_char, time::Duration};
1013
1014 use libc::{in_addr_t, in_port_t};
1015 use rand::{Rng, RngExt};
1016 use shadow_shim_helper_rs::shim_shmem;
1017
1018 use super::*;
1019 use crate::cshadow::{CEmulatedTime, CSimulationTime};
1020 use crate::network::packet::IanaProtocol;
1021
1022 #[unsafe(no_mangle)]
1023 pub unsafe extern "C-unwind" fn host_execute(hostrc: *const Host, until: CEmulatedTime) {
1024 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1025 let until = EmulatedTime::from_c_emutime(until).unwrap();
1026 hostrc.execute(until)
1027 }
1028
1029 #[unsafe(no_mangle)]
1030 pub unsafe extern "C-unwind" fn host_nextEventTime(hostrc: *const Host) -> CEmulatedTime {
1031 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1032 EmulatedTime::to_c_emutime(hostrc.next_event_time())
1033 }
1034
1035 #[unsafe(no_mangle)]
1036 pub unsafe extern "C-unwind" fn host_getNewPacketID(hostrc: *const Host) -> u64 {
1037 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1038 hostrc.get_new_packet_id()
1039 }
1040
1041 #[unsafe(no_mangle)]
1042 pub unsafe extern "C-unwind" fn host_freeAllApplications(hostrc: *const Host) {
1043 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1044 hostrc.free_all_applications()
1045 }
1046
1047 #[unsafe(no_mangle)]
1048 pub unsafe extern "C-unwind" fn host_getID(hostrc: *const Host) -> HostId {
1049 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1050 hostrc.id()
1051 }
1052
1053 #[unsafe(no_mangle)]
1056 pub unsafe extern "C-unwind" fn host_getTsc(host: *const Host) -> *const Tsc {
1057 let hostrc = unsafe { host.as_ref().unwrap() };
1058 hostrc.tsc()
1059 }
1060
1061 #[unsafe(no_mangle)]
1062 pub unsafe extern "C-unwind" fn host_getName(hostrc: *const Host) -> *const c_char {
1063 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1064 hostrc.params.hostname.as_ptr()
1065 }
1066
1067 #[unsafe(no_mangle)]
1068 pub unsafe extern "C-unwind" fn host_getDefaultIP(hostrc: *const Host) -> in_addr_t {
1069 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1070 let ip = hostrc.default_ip();
1071 u32::from(ip).to_be()
1072 }
1073
1074 #[unsafe(no_mangle)]
1075 pub unsafe extern "C-unwind" fn host_getNextPacketPriority(
1076 hostrc: *const Host,
1077 ) -> FifoPacketPriority {
1078 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1079 hostrc.get_next_packet_priority()
1080 }
1081
1082 #[unsafe(no_mangle)]
1083 pub unsafe extern "C-unwind" fn host_autotuneReceiveBuffer(hostrc: *const Host) -> bool {
1084 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1085 hostrc.params.autotune_recv_buf
1086 }
1087
1088 #[unsafe(no_mangle)]
1089 pub unsafe extern "C-unwind" fn host_autotuneSendBuffer(hostrc: *const Host) -> bool {
1090 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1091 hostrc.params.autotune_send_buf
1092 }
1093
1094 #[unsafe(no_mangle)]
1095 pub unsafe extern "C-unwind" fn host_getConfiguredRecvBufSize(hostrc: *const Host) -> u64 {
1096 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1097 hostrc.params.init_sock_recv_buf_size
1098 }
1099
1100 #[unsafe(no_mangle)]
1101 pub unsafe extern "C-unwind" fn host_getConfiguredSendBufSize(hostrc: *const Host) -> u64 {
1102 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1103 hostrc.params.init_sock_send_buf_size
1104 }
1105
1106 #[unsafe(no_mangle)]
1107 pub unsafe extern "C-unwind" fn host_getUpstreamRouter(hostrc: *const Host) -> *mut Router {
1108 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1109 &mut *hostrc.upstream_router_borrow_mut()
1110 }
1111
1112 #[unsafe(no_mangle)]
1113 pub unsafe extern "C-unwind" fn host_get_bw_down_kiBps(hostrc: *const Host) -> u64 {
1114 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1115 hostrc.bw_down_kiBps()
1116 }
1117
1118 #[unsafe(no_mangle)]
1119 pub unsafe extern "C-unwind" fn host_get_bw_up_kiBps(hostrc: *const Host) -> u64 {
1120 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1121 hostrc.bw_up_kiBps()
1122 }
1123
1124 #[unsafe(no_mangle)]
1127 pub unsafe extern "C-unwind" fn host_getDataPath(hostrc: *const Host) -> *const c_char {
1128 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1129 hostrc.data_dir_path_cstring.as_ptr()
1130 }
1131
1132 #[unsafe(no_mangle)]
1133 pub unsafe extern "C-unwind" fn host_disassociateInterface(
1134 hostrc: *const Host,
1135 c_protocol: cshadow::ProtocolType,
1136 bind_ip: in_addr_t,
1137 bind_port: in_port_t,
1138 peer_ip: in_addr_t,
1139 peer_port: in_port_t,
1140 ) {
1141 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1142
1143 let bind_ip = Ipv4Addr::from(u32::from_be(bind_ip));
1144 let peer_ip = Ipv4Addr::from(u32::from_be(peer_ip));
1145 let bind_port = u16::from_be(bind_port);
1146 let peer_port = u16::from_be(peer_port);
1147
1148 let bind_addr = SocketAddrV4::new(bind_ip, bind_port);
1149 let peer_addr = SocketAddrV4::new(peer_ip, peer_port);
1150
1151 let protocol = IanaProtocol::from(c_protocol);
1152
1153 hostrc
1155 .net_ns
1156 .disassociate_interface(protocol, bind_addr, peer_addr);
1157 }
1158
1159 #[unsafe(no_mangle)]
1160 pub unsafe extern "C-unwind" fn host_getRandomFreePort(
1161 hostrc: *const Host,
1162 c_protocol: cshadow::ProtocolType,
1163 interface_ip: in_addr_t,
1164 peer_ip: in_addr_t,
1165 peer_port: in_port_t,
1166 ) -> in_port_t {
1167 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1168
1169 let interface_ip = Ipv4Addr::from(u32::from_be(interface_ip));
1170 let peer_addr = SocketAddrV4::new(
1171 Ipv4Addr::from(u32::from_be(peer_ip)),
1172 u16::from_be(peer_port),
1173 );
1174
1175 let protocol = IanaProtocol::from(c_protocol);
1176
1177 hostrc
1178 .net_ns
1179 .get_random_free_port(
1180 protocol,
1181 interface_ip,
1182 peer_addr,
1183 hostrc.random.borrow_mut().deref_mut(),
1184 )
1185 .unwrap_or(0)
1186 .to_be()
1187 }
1188
1189 #[unsafe(no_mangle)]
1195 pub unsafe extern "C-unwind" fn host_getFutexTable(hostrc: *const Host) -> *mut FutexTable {
1196 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1197 &mut *hostrc.futextable_borrow_mut()
1198 }
1199
1200 #[unsafe(no_mangle)]
1202 pub unsafe extern "C-unwind" fn host_getProcess(
1203 host: *const Host,
1204 virtual_pid: libc::pid_t,
1205 ) -> *const Process {
1206 let host = unsafe { host.as_ref().unwrap() };
1207 let virtual_pid = ProcessId::try_from(virtual_pid).unwrap();
1208 host.process_borrow(virtual_pid)
1209 .map(|x| std::ptr::from_ref(&*x.borrow(host.root())))
1210 .unwrap_or(std::ptr::null_mut())
1211 }
1212
1213 #[unsafe(no_mangle)]
1222 pub unsafe extern "C-unwind" fn host_getThread(
1223 host: *const Host,
1224 virtual_tid: libc::pid_t,
1225 ) -> *const Thread {
1226 let host = unsafe { host.as_ref().unwrap() };
1227 let tid = ThreadId::try_from(virtual_tid).unwrap();
1228 for process in host.processes.borrow().values() {
1229 let process = process.borrow(host.root());
1230 if let Some(thread) = process.thread_borrow(tid) {
1231 let thread = thread.borrow(host.root());
1242 return std::ptr::from_ref(&*thread);
1243 };
1244 }
1245 std::ptr::null_mut()
1246 }
1247
1248 #[unsafe(no_mangle)]
1260 pub unsafe extern "C-unwind" fn host_getShimShmemLock(
1261 hostrc: *const Host,
1262 ) -> *mut shim_shmem::export::ShimShmemHostLock {
1263 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1264 let mut opt_lock = hostrc.shim_shmem_lock.borrow_mut();
1265 let lock = opt_lock.as_mut().unwrap();
1266 unsafe { lock.get().as_mut().unwrap().deref_mut() }
1269 }
1270
1271 #[unsafe(no_mangle)]
1273 pub unsafe extern "C-unwind" fn host_lockShimShmemLock(hostrc: *const Host) {
1274 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1275 hostrc.lock_shmem()
1276 }
1277
1278 #[unsafe(no_mangle)]
1280 pub unsafe extern "C-unwind" fn host_unlockShimShmemLock(hostrc: *const Host) {
1281 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1282 hostrc.unlock_shmem()
1283 }
1284
1285 #[unsafe(no_mangle)]
1290 pub unsafe extern "C-unwind" fn host_getNextDeterministicSequenceValue(
1291 hostrc: *const Host,
1292 ) -> u64 {
1293 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1294 hostrc.get_next_deterministic_sequence_value()
1295 }
1296
1297 #[unsafe(no_mangle)]
1299 pub unsafe extern "C-unwind" fn host_scheduleTaskAtEmulatedTime(
1300 hostrc: *const Host,
1301 task: *mut TaskRef,
1302 time: CEmulatedTime,
1303 ) -> bool {
1304 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1305 let task = unsafe { task.as_ref().unwrap().clone() };
1306 let time = EmulatedTime::from_c_emutime(time).unwrap();
1307 hostrc.schedule_task_at_emulated_time(task, time)
1308 }
1309
1310 #[unsafe(no_mangle)]
1312 pub unsafe extern "C-unwind" fn host_scheduleTaskWithDelay(
1313 hostrc: *const Host,
1314 task: *mut TaskRef,
1315 delay: CSimulationTime,
1316 ) -> bool {
1317 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1318 let task = unsafe { task.as_ref().unwrap().clone() };
1319 let delay = SimulationTime::from_c_simtime(delay).unwrap();
1320 hostrc.schedule_task_with_delay(task, delay)
1321 }
1322
1323 #[unsafe(no_mangle)]
1324 pub unsafe extern "C-unwind" fn host_rngDouble(host: *const Host) -> f64 {
1325 let host = unsafe { host.as_ref().unwrap() };
1326 host.random_mut().random()
1327 }
1328
1329 #[unsafe(no_mangle)]
1331 pub extern "C-unwind" fn host_rngNextNBytes(host: *const Host, buf: *mut u8, len: usize) {
1332 let host = unsafe { host.as_ref().unwrap() };
1333 let buf = unsafe { std::slice::from_raw_parts_mut(buf, len) };
1334 host.random_mut().fill_bytes(buf);
1335 }
1336
1337 #[unsafe(no_mangle)]
1338 pub extern "C-unwind" fn host_paramsCpuFrequencyHz(host: *const Host) -> u64 {
1339 let host = unsafe { host.as_ref().unwrap() };
1340 host.params.cpu_frequency
1341 }
1342
1343 #[unsafe(no_mangle)]
1344 pub extern "C-unwind" fn host_addDelayNanos(host: *const Host, delay_nanos: u64) {
1345 let host = unsafe { host.as_ref().unwrap() };
1346 let delay = Duration::from_nanos(delay_nanos);
1347 host.cpu.borrow_mut().add_delay(delay);
1348 }
1349
1350 #[unsafe(no_mangle)]
1351 pub unsafe extern "C-unwind" fn host_socketWantsToSend(
1352 hostrc: *const Host,
1353 socket: *const InetSocket,
1354 addr: in_addr_t,
1355 ) {
1356 let host = unsafe { hostrc.as_ref().unwrap() };
1357 let socket = unsafe { socket.as_ref().unwrap() };
1358 let addr = u32::from_be(addr).into();
1359 host.notify_socket_has_packets(addr, socket);
1360 }
1361
1362 #[unsafe(no_mangle)]
1363 pub unsafe extern "C-unwind" fn host_continue(
1364 host: *const Host,
1365 pid: libc::pid_t,
1366 tid: libc::pid_t,
1367 ) {
1368 let host = unsafe { host.as_ref().unwrap() };
1369 host.resume(pid.try_into().unwrap(), tid.try_into().unwrap())
1370 }
1371}