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::futex_table::FutexTable;
42use crate::host::network::interface::{FifoPacketPriority, NetworkInterface, PcapOptions};
43use crate::host::network::namespace::NetworkNamespace;
44use crate::host::process::Process;
45use crate::host::thread::{Thread, ThreadId};
46use crate::network::PacketDevice;
47use crate::network::relay::{RateLimit, Relay};
48use crate::network::router::Router;
49use crate::utility;
50#[cfg(feature = "perf_timers")]
51use crate::utility::perf_timer::PerfTimer;
52
53pub struct HostParameters {
54 pub id: HostId,
55 pub node_seed: u64,
56 pub hostname: CString,
59 pub node_id: u32,
60 pub ip_addr: libc::in_addr_t,
61 pub sim_end_time: EmulatedTime,
62 pub requested_bw_down_bits: u64,
63 pub requested_bw_up_bits: u64,
64 pub cpu_frequency: u64,
65 pub cpu_threshold: Option<SimulationTime>,
66 pub cpu_precision: Option<SimulationTime>,
67 pub log_level: LogLevel,
68 pub pcap_config: Option<PcapConfig>,
69 pub qdisc: QDiscMode,
70 pub init_sock_recv_buf_size: u64,
71 pub autotune_recv_buf: bool,
72 pub init_sock_send_buf_size: u64,
73 pub autotune_send_buf: bool,
74 pub native_tsc_frequency: u64,
75 pub model_unblocked_syscall_latency: bool,
76 pub max_unapplied_cpu_latency: SimulationTime,
77 pub unblocked_syscall_latency: SimulationTime,
78 pub unblocked_vdso_latency: SimulationTime,
79 pub strace_logging_options: Option<FmtOptions>,
80 pub shim_log_level: LogLevel,
81 pub use_new_tcp: bool,
82 pub use_mem_mapper: 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 #[cfg(feature = "perf_timers")]
135 execution_timer: RefCell<PerfTimer>,
136
137 pub params: HostParameters,
138
139 cpu: RefCell<Cpu>,
140
141 net_ns: NetworkNamespace,
142
143 data_dir_path: PathBuf,
149 data_dir_path_cstring: CString,
150
151 thread_id_counter: Cell<libc::pid_t>,
153 event_id_counter: Cell<u64>,
154 packet_id_counter: Cell<u64>,
155
156 determinism_sequence_counter: Cell<u64>,
158
159 packet_priority_counter: Cell<FifoPacketPriority>,
161
162 processes: RefCell<BTreeMap<ProcessId, RootedRc<RootedRefCell<Process>>>>,
164
165 tsc: Tsc,
166 shim_shmem_lock:
177 RefCell<Option<UnsafeCell<SelfContainedMutexGuard<'static, HostShmemProtected>>>>,
178 shim_shmem: UnsafeCell<ShMemBlock<'static, HostShmem>>,
190
191 in_notify_socket_has_packets: RootedCell<bool>,
192
193 preload_paths: Arc<Vec<PathBuf>>,
195}
196
197impl crate::utility::IsSend for Host {}
199
200impl std::fmt::Debug for Host {
202 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
203 f.debug_struct("Host")
204 .field("info", &self.info)
205 .finish_non_exhaustive()
206 }
207}
208
209impl Host {
210 pub fn new(
211 params: HostParameters,
212 host_root_path: &Path,
213 raw_cpu_freq_khz: u64,
214 manager_shmem: &ShMemBlock<ManagerShmem>,
215 preload_paths: Arc<Vec<PathBuf>>,
216 ) -> Self {
217 #[cfg(feature = "perf_timers")]
218 let execution_timer = RefCell::new(PerfTimer::new_started());
219
220 let root = Root::new();
221 let random = RefCell::new(Xoshiro256PlusPlus::seed_from_u64(params.node_seed));
222 let cpu = RefCell::new(Cpu::new(
223 params.cpu_frequency,
224 raw_cpu_freq_khz,
225 params.cpu_threshold,
226 params.cpu_precision,
227 ));
228 let data_dir_path = Self::make_data_dir_path(¶ms.hostname, host_root_path);
229 let data_dir_path_cstring = utility::pathbuf_to_nul_term_cstring(data_dir_path.clone());
230
231 let host_shmem = HostShmem::new(
232 params.id,
233 params.model_unblocked_syscall_latency,
234 params.max_unapplied_cpu_latency,
235 params.unblocked_syscall_latency,
236 params.unblocked_vdso_latency,
237 nix::unistd::getpid().as_raw(),
238 params.native_tsc_frequency,
239 params.shim_log_level,
240 manager_shmem,
241 );
242 let shim_shmem = UnsafeCell::new(shadow_shmem::allocator::shmalloc(host_shmem));
243
244 let thread_id_counter = Cell::new(1000);
246 let event_id_counter = Cell::new(0);
247 let packet_id_counter = Cell::new(0);
248 let determinism_sequence_counter = Cell::new(0);
249 let packet_priority_counter = Cell::new(1);
251 let tsc = Tsc::new(params.native_tsc_frequency);
252
253 std::fs::create_dir_all(&data_dir_path).unwrap();
254
255 let public_ip: Ipv4Addr = u32::from_be(params.ip_addr).into();
259
260 let pcap_options = params.pcap_config.as_ref().map(|x| PcapOptions {
261 path: data_dir_path.clone(),
262 capture_size_bytes: x.capture_size.try_into().unwrap(),
263 });
264
265 let net_ns = NetworkNamespace::new(public_ip, pcap_options, params.qdisc);
266
267 let router = Router::new(Ipv4Addr::UNSPECIFIED);
271 let relay_inet_out = Relay::new(
272 RateLimit::BytesPerSecond(params.requested_bw_up_bits / 8),
273 net_ns.internet.borrow().get_address(),
274 );
275 let relay_inet_in = Relay::new(
276 RateLimit::BytesPerSecond(params.requested_bw_down_bits / 8),
277 router.get_address(),
278 );
279 let relay_loopback = Relay::new(
280 RateLimit::Unlimited,
281 net_ns.localhost.borrow().get_address(),
282 );
283
284 let in_notify_socket_has_packets = RootedCell::new(&root, false);
285
286 let res = Self {
287 info: OnceCell::new(),
288 root,
289 event_queue: Arc::new(Mutex::new(EventQueue::new())),
290 params,
291 router: RefCell::new(router),
292 relay_inet_out: Arc::new(relay_inet_out),
293 relay_inet_in: Arc::new(relay_inet_in),
294 relay_loopback: Arc::new(relay_loopback),
295 futex_table: RefCell::new(FutexTable::new()),
296 random,
297 shim_shmem,
298 shim_shmem_lock: RefCell::new(None),
299 cpu,
300 net_ns,
301 data_dir_path,
302 data_dir_path_cstring,
303 thread_id_counter,
304 event_id_counter,
305 packet_id_counter,
306 packet_priority_counter,
307 determinism_sequence_counter,
308 tsc,
309 processes: RefCell::new(BTreeMap::new()),
310 #[cfg(feature = "perf_timers")]
311 execution_timer,
312 in_notify_socket_has_packets,
313 preload_paths,
314 };
315
316 res.stop_execution_timer();
317
318 debug!(
319 concat!(
320 "Setup host id '{:?}'",
321 " name '{name}'",
322 " with seed {seed},",
323 " {bw_up_kiBps} bwUpKiBps,",
324 " {bw_down_kiBps} bwDownKiBps,",
325 " {init_sock_send_buf_size} initSockSendBufSize,",
326 " {init_sock_recv_buf_size} initSockRecvBufSize, ",
327 " {cpu_frequency:?} cpuFrequency, ",
328 " {cpu_threshold:?} cpuThreshold, ",
329 " {cpu_precision:?} cpuPrecision"
330 ),
331 res.id(),
332 name = res.info().name,
333 seed = res.params.node_seed,
334 bw_up_kiBps = res.bw_up_kiBps(),
335 bw_down_kiBps = res.bw_down_kiBps(),
336 init_sock_send_buf_size = res.params.init_sock_send_buf_size,
337 init_sock_recv_buf_size = res.params.init_sock_recv_buf_size,
338 cpu_frequency = res.params.cpu_frequency,
339 cpu_threshold = res.params.cpu_threshold,
340 cpu_precision = res.params.cpu_precision,
341 );
342
343 res
344 }
345
346 pub fn root(&self) -> &Root {
347 &self.root
348 }
349
350 fn make_data_dir_path(hostname: &CStr, host_root_path: &Path) -> PathBuf {
351 let hostname: OsString = { OsString::from_vec(hostname.to_bytes().to_vec()) };
352
353 let mut data_dir_path = PathBuf::new();
354 data_dir_path.push(host_root_path);
355 data_dir_path.push(&hostname);
356 data_dir_path
357 }
358
359 pub fn data_dir_path(&self) -> &Path {
360 &self.data_dir_path
361 }
362
363 pub fn add_application(
364 &self,
365 start_time: SimulationTime,
366 shutdown_time: Option<SimulationTime>,
367 shutdown_signal: nix::sys::signal::Signal,
368 plugin_name: CString,
369 plugin_path: CString,
370 argv: Vec<CString>,
371 envv: Vec<CString>,
372 pause_for_debugging: bool,
373 expected_final_state: ProcessFinalState,
374 ) {
375 debug_assert!(shutdown_time.is_none() || shutdown_time.unwrap() > start_time);
376
377 let task = TaskRef::new(move |host| {
379 let envv = envv.clone();
383 let argv = argv.clone();
384
385 let process = Process::spawn(
386 host,
387 plugin_name.clone(),
388 &plugin_path,
389 argv,
390 envv,
391 pause_for_debugging,
392 host.params.strace_logging_options,
393 expected_final_state,
394 )
395 .unwrap_or_else(|e| panic!("Failed to initialize application {plugin_name:?}: {e:?}"));
396 let (process_id, thread_id) = {
397 let process = process.borrow(host.root());
398 (process.id(), process.thread_group_leader_id())
399 };
400 host.processes.borrow_mut().insert(process_id, process);
401
402 if let Some(shutdown_time) = shutdown_time {
403 let task = TaskRef::new(move |host| {
404 let Some(process) = host.process_borrow(process_id) else {
405 debug!(
406 "Can't send shutdown signal to process {process_id}; it no longer exists"
407 );
408 return;
409 };
410 let process = process.borrow(host.root());
411 let siginfo_t = siginfo_t::new_for_kill(
412 Signal::try_from(shutdown_signal as i32).unwrap(),
413 1,
414 0,
415 );
416 process.signal(host, None, &siginfo_t);
417 });
418 host.schedule_task_at_emulated_time(
419 task,
420 EmulatedTime::SIMULATION_START + shutdown_time,
421 );
422 }
423
424 host.resume(process_id, thread_id);
425 });
426 self.schedule_task_at_emulated_time(task, EmulatedTime::SIMULATION_START + start_time);
427 }
428
429 pub fn add_and_schedule_forked_process(
430 &self,
431 host: &Host,
432 process: RootedRc<RootedRefCell<Process>>,
433 ) {
434 let (process_id, thread_id) = {
435 let process = process.borrow(&self.root);
436 (process.id(), process.thread_group_leader_id())
437 };
438 host.processes.borrow_mut().insert(process_id, process);
439 let task = TaskRef::new(move |host| {
441 host.resume(process_id, thread_id);
442 });
443 self.schedule_task_with_delay(task, SimulationTime::ZERO);
444 }
445
446 pub fn resume(&self, pid: ProcessId, tid: ThreadId) {
447 let Some(processrc) = self
448 .process_borrow(pid)
449 .map(|p| RootedRc::clone(&p, &self.root))
450 else {
451 trace!("{pid:?} doesn't exist");
452 return;
453 };
454 let processrc = ExplicitDropper::new(processrc, |p| {
455 p.explicit_drop_recursive(&self.root, self);
456 });
457 let died;
458 let is_orphan;
459 {
460 Worker::set_active_process(&processrc);
461 let process = processrc.borrow(self.root());
462 process.resume(self, tid);
463 Worker::clear_active_process();
464 let zombie_state = process.borrow_as_zombie();
465 if let Some(zombie) = zombie_state {
466 died = true;
467 is_orphan = zombie.reaper(self).is_none();
468 } else {
469 died = false;
470 is_orphan = false;
471 }
472 };
473
474 if !died {
475 return;
476 }
477
478 let mut orphaned_zombie_pids: Vec<ProcessId> = self
480 .processes
481 .borrow()
482 .iter()
483 .filter_map(|(other_pid, processrc)| {
484 let process = processrc.borrow(&self.root);
485 if process.parent_id() != pid {
486 return None;
488 }
489 process.set_parent_id(ProcessId::INIT);
490 let Some(z) = process.borrow_as_zombie() else {
491 return None;
493 };
494 if z.reaper(self).is_some() {
495 None
497 } else {
498 Some(*other_pid)
500 }
501 })
502 .collect();
503
504 debug_assert!(died);
506 if is_orphan {
507 orphaned_zombie_pids.push(pid);
508 }
509
510 let mut processes = self.processes.borrow_mut();
512 for pid in orphaned_zombie_pids {
513 trace!("Dropping orphan zombie process {pid:?}");
514 let processrc = processes.remove(&pid).unwrap();
515 RootedRc::explicit_drop_recursive(processrc, &self.root, self);
516 }
517 }
518
519 #[track_caller]
520 pub fn process_borrow(
521 &self,
522 id: ProcessId,
523 ) -> Option<impl Deref<Target = RootedRc<RootedRefCell<Process>>> + '_> {
524 Ref::filter_map(self.processes.borrow(), |processes| processes.get(&id)).ok()
525 }
526
527 #[track_caller]
529 pub fn process_remove(&self, id: ProcessId) -> Option<RootedRc<RootedRefCell<Process>>> {
530 self.processes.borrow_mut().remove(&id)
531 }
532
533 #[track_caller]
542 pub fn processes_borrow(
543 &self,
544 ) -> impl Deref<Target = BTreeMap<ProcessId, RootedRc<RootedRefCell<Process>>>> + '_ {
545 self.processes.borrow()
546 }
547
548 pub fn cpu_borrow(&self) -> impl Deref<Target = Cpu> + '_ {
549 self.cpu.borrow()
550 }
551
552 pub fn cpu_borrow_mut(&self) -> impl DerefMut<Target = Cpu> + '_ {
553 self.cpu.borrow_mut()
554 }
555
556 pub fn info(&self) -> &Arc<HostInfo> {
561 self.info.get_or_init(|| {
562 Arc::new(HostInfo {
563 id: self.id(),
564 name: self.params.hostname.to_str().unwrap().to_owned(),
565 default_ip: self.default_ip(),
566 log_level: self.log_level(),
567 })
568 })
569 }
570
571 pub fn id(&self) -> HostId {
572 self.params.id
573 }
574
575 pub fn name(&self) -> &str {
576 &self.info().name
577 }
578
579 pub fn default_ip(&self) -> Ipv4Addr {
580 self.net_ns.default_ip
581 }
582
583 pub fn abstract_unix_namespace(
584 &self,
585 ) -> impl Deref<Target = Arc<AtomicRefCell<AbstractUnixNamespace>>> + '_ {
586 &self.net_ns.unix
587 }
588
589 pub fn log_level(&self) -> Option<log::LevelFilter> {
590 let level = self.params.log_level;
591 log_c2rust::c_to_rust_log_level(level).map(|l| l.to_level_filter())
592 }
593
594 #[track_caller]
595 pub fn upstream_router_borrow_mut(&self) -> impl DerefMut<Target = Router> + '_ {
596 self.router.borrow_mut()
597 }
598
599 #[track_caller]
600 pub fn network_namespace_borrow(&self) -> impl Deref<Target = NetworkNamespace> + '_ {
601 &self.net_ns
602 }
603
604 #[track_caller]
605 pub fn futextable_borrow(&self) -> impl Deref<Target = FutexTable> + '_ {
606 self.futex_table.borrow()
607 }
608
609 #[track_caller]
610 pub fn futextable_borrow_mut(&self) -> impl DerefMut<Target = FutexTable> + '_ {
611 self.futex_table.borrow_mut()
612 }
613
614 #[allow(non_snake_case)]
615 pub fn bw_up_kiBps(&self) -> u64 {
616 self.params.requested_bw_up_bits / (8 * 1024)
617 }
618
619 #[allow(non_snake_case)]
620 pub fn bw_down_kiBps(&self) -> u64 {
621 self.params.requested_bw_down_bits / (8 * 1024)
622 }
623
624 pub fn interface_borrow_mut(
628 &self,
629 addr: Ipv4Addr,
630 ) -> Option<impl DerefMut<Target = NetworkInterface> + '_> {
631 self.net_ns.interface_borrow_mut(addr)
632 }
633
634 pub fn interface_borrow(
638 &self,
639 addr: Ipv4Addr,
640 ) -> Option<impl Deref<Target = NetworkInterface> + '_> {
641 self.net_ns.interface_borrow(addr)
642 }
643
644 #[track_caller]
645 pub fn random_mut(&self) -> impl DerefMut<Target = Xoshiro256PlusPlus> + '_ {
646 self.random.borrow_mut()
647 }
648
649 pub fn get_new_event_id(&self) -> u64 {
650 let res = self.event_id_counter.get();
651 self.event_id_counter.set(res + 1);
652 res
653 }
654
655 pub fn get_new_thread_id(&self) -> ThreadId {
656 let res = self.thread_id_counter.get();
657 self.thread_id_counter.set(res + 1);
658 res.try_into().unwrap()
659 }
660
661 pub fn get_new_packet_id(&self) -> u64 {
662 let res = self.packet_id_counter.get();
663 self.packet_id_counter.set(res + 1);
664 res
665 }
666
667 pub fn get_next_deterministic_sequence_value(&self) -> u64 {
668 let res = self.determinism_sequence_counter.get();
669 self.determinism_sequence_counter.set(res + 1);
670 res
671 }
672
673 pub fn get_next_packet_priority(&self) -> FifoPacketPriority {
674 let res = self.packet_priority_counter.get();
675 self.packet_priority_counter
676 .set(res.checked_add(1).unwrap());
677 res
678 }
679
680 pub fn continue_execution_timer(&self) {
681 #[cfg(feature = "perf_timers")]
682 self.execution_timer.borrow_mut().start();
683 }
684
685 pub fn stop_execution_timer(&self) {
686 #[cfg(feature = "perf_timers")]
687 self.execution_timer.borrow_mut().stop();
688 }
689
690 pub fn schedule_task_at_emulated_time(&self, task: TaskRef, t: EmulatedTime) -> bool {
691 let event = Event::new_local(task, t, self);
692 self.push_local_event(event)
693 }
694
695 pub fn schedule_task_with_delay(&self, task: TaskRef, t: SimulationTime) -> bool {
696 self.schedule_task_at_emulated_time(task, Worker::current_time().unwrap() + t)
697 }
698
699 pub fn event_queue(&self) -> &Arc<Mutex<EventQueue>> {
700 &self.event_queue
701 }
702
703 pub fn push_local_event(&self, event: Event) -> bool {
704 if event.time() >= self.params.sim_end_time {
705 return false;
706 }
707 self.event_queue.lock().unwrap().push(event);
708 true
709 }
710
711 pub fn shutdown(&self) {
713 self.continue_execution_timer();
714
715 debug!("shutting down host {}", self.name());
716
717 self.net_ns.cleanup();
719
720 assert!(self.processes.borrow().is_empty());
721
722 self.stop_execution_timer();
723 #[cfg(feature = "perf_timers")]
724 debug!(
725 "host '{}' has been shut down, total execution time was {:?}",
726 self.name(),
727 self.execution_timer.borrow().elapsed()
728 );
729 }
730
731 pub fn free_all_applications(&self) {
732 trace!("start freeing applications for host '{}'", self.name());
733 let processes = std::mem::take(&mut *self.processes.borrow_mut());
734 for (_id, processrc) in processes.into_iter() {
735 let processrc = ExplicitDropper::new(processrc, |p| {
736 p.explicit_drop_recursive(self.root(), self);
737 });
738 Worker::set_active_process(&processrc);
739 let process = processrc.borrow(self.root());
740 process.stop(self);
741 Worker::clear_active_process();
742 process.set_parent_id(ProcessId::INIT);
745 }
746 trace!("done freeing application for host '{}'", self.name());
747 }
748
749 pub fn execute(&self, until: EmulatedTime) {
750 loop {
751 let mut event = {
752 let mut event_queue = self.event_queue.lock().unwrap();
753 match event_queue.next_event_time() {
754 Some(t) if t < until => {}
755 _ => break,
756 };
757 event_queue.pop().unwrap()
758 };
759
760 {
761 let mut cpu = self.cpu.borrow_mut();
762 cpu.update_time(event.time());
763 let cpu_delay = cpu.delay();
764 if cpu_delay > SimulationTime::ZERO {
765 trace!("event blocked on CPU, rescheduled for {cpu_delay:?} from now");
766
767 event.set_time(event.time() + cpu_delay);
769 self.push_local_event(event);
770
771 continue;
773 }
774 }
775
776 Worker::set_current_time(event.time());
778 self.continue_execution_timer();
779 match event.data() {
780 EventData::Packet(data) => {
781 self.upstream_router_borrow_mut()
782 .route_incoming_packet(data.into());
783 self.notify_router_has_packets();
784 }
785 EventData::Local(data) => TaskRef::from(data).execute(self),
786 }
787 self.stop_execution_timer();
788 Worker::clear_current_time();
789 }
790 }
791
792 pub fn next_event_time(&self) -> Option<EmulatedTime> {
793 self.event_queue.lock().unwrap().next_event_time()
794 }
795
796 pub fn shim_shmem(&self) -> &ShMemBlock<'static, HostShmem> {
802 unsafe { &*self.shim_shmem.get() }
803 }
804
805 pub fn thread_cloned_rc(
808 &self,
809 virtual_tid: ThreadId,
810 ) -> Option<RootedRc<RootedRefCell<Thread>>> {
811 for process in self.processes.borrow().values() {
812 let process = process.borrow(self.root());
813 if let Some(thread) = process.thread_borrow(virtual_tid) {
814 return Some(RootedRc::clone(&*thread, self.root()));
815 };
816 }
817
818 None
819 }
820
821 pub fn has_thread(&self, virtual_tid: ThreadId) -> bool {
823 for process in self.processes.borrow().values() {
824 let process = process.borrow(self.root());
825 if process.thread_borrow(virtual_tid).is_some() {
826 return true;
827 }
828 }
829
830 false
831 }
832
833 pub fn lock_shmem(&self) {
839 let shim_shmem: &'static ShMemBlock<HostShmem> =
851 unsafe { self.shim_shmem.get().as_ref().unwrap() };
852 let lock = shim_shmem.protected().lock();
853 let prev = self
854 .shim_shmem_lock
855 .borrow_mut()
856 .replace(UnsafeCell::new(lock));
857 assert!(prev.is_none());
858 }
859
860 pub fn unlock_shmem(&self) {
863 let prev = self.shim_shmem_lock.borrow_mut().take();
864 assert!(prev.is_some());
865 }
866
867 pub fn shim_shmem_lock_borrow(&self) -> Option<impl Deref<Target = HostShmemProtected> + '_> {
868 Ref::filter_map(self.shim_shmem_lock.borrow(), |l| {
869 l.as_ref().map(|l| {
870 let guard = unsafe { &*l.get() };
874 guard.deref()
875 })
876 })
877 .ok()
878 }
879
880 pub fn shim_shmem_lock_borrow_mut(
881 &self,
882 ) -> Option<impl DerefMut<Target = HostShmemProtected> + '_> {
883 RefMut::filter_map(self.shim_shmem_lock.borrow_mut(), |l| {
884 l.as_ref().map(|l| {
885 let guard = unsafe { &mut *l.get() };
889 guard.deref_mut()
890 })
891 })
892 .ok()
893 }
894
895 pub fn tsc(&self) -> &Tsc {
898 &self.tsc
899 }
900
901 pub fn get_packet_device(&self, address: Ipv4Addr) -> Ref<dyn PacketDevice> {
907 if address == Ipv4Addr::LOCALHOST {
908 self.net_ns.localhost.borrow()
909 } else if address == self.default_ip() {
910 self.net_ns.internet.borrow()
911 } else {
912 self.router.borrow()
913 }
914 }
915
916 pub fn notify_router_has_packets(&self) {
919 self.relay_inet_in.notify(self);
920 }
921
922 pub fn notify_socket_has_packets(&self, addr: Ipv4Addr, socket: &InetSocket) {
930 if self.in_notify_socket_has_packets.replace(&self.root, true) {
931 panic!("Recursively calling host.notify_socket_has_packets()");
932 }
933
934 if let Some(iface) = self.interface_borrow(addr) {
935 iface.add_data_source(socket);
936 match addr {
937 Ipv4Addr::LOCALHOST => self.relay_loopback.notify(self),
938 _ => self.relay_inet_out.notify(self),
939 };
940 }
941
942 self.in_notify_socket_has_packets.set(&self.root, false);
943 }
944
945 pub fn process_session_id_of_group_id(&self, group_id: ProcessId) -> Option<ProcessId> {
947 let processes = self.processes.borrow();
948 for processrc in processes.values() {
949 let process = processrc.borrow(&self.root);
950 if process.group_id() == group_id {
951 return Some(process.session_id());
952 }
953 }
954 None
955 }
956
957 pub fn preload_paths(&self) -> &[PathBuf] {
959 &self.preload_paths
960 }
961}
962
963impl Drop for Host {
964 fn drop(&mut self) {
965 assert!(self.shim_shmem_lock.borrow().is_none());
969 }
970}
971
972mod export {
973 use std::{os::raw::c_char, time::Duration};
974
975 use libc::{in_addr_t, in_port_t};
976 use rand::{Rng, RngCore};
977 use shadow_shim_helper_rs::shim_shmem;
978
979 use super::*;
980 use crate::cshadow::{CEmulatedTime, CSimulationTime};
981 use crate::network::packet::IanaProtocol;
982
983 #[unsafe(no_mangle)]
984 pub unsafe extern "C-unwind" fn host_execute(hostrc: *const Host, until: CEmulatedTime) {
985 let hostrc = unsafe { hostrc.as_ref().unwrap() };
986 let until = EmulatedTime::from_c_emutime(until).unwrap();
987 hostrc.execute(until)
988 }
989
990 #[unsafe(no_mangle)]
991 pub unsafe extern "C-unwind" fn host_nextEventTime(hostrc: *const Host) -> CEmulatedTime {
992 let hostrc = unsafe { hostrc.as_ref().unwrap() };
993 EmulatedTime::to_c_emutime(hostrc.next_event_time())
994 }
995
996 #[unsafe(no_mangle)]
997 pub unsafe extern "C-unwind" fn host_getNewPacketID(hostrc: *const Host) -> u64 {
998 let hostrc = unsafe { hostrc.as_ref().unwrap() };
999 hostrc.get_new_packet_id()
1000 }
1001
1002 #[unsafe(no_mangle)]
1003 pub unsafe extern "C-unwind" fn host_freeAllApplications(hostrc: *const Host) {
1004 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1005 hostrc.free_all_applications()
1006 }
1007
1008 #[unsafe(no_mangle)]
1009 pub unsafe extern "C-unwind" fn host_getID(hostrc: *const Host) -> HostId {
1010 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1011 hostrc.id()
1012 }
1013
1014 #[unsafe(no_mangle)]
1017 pub unsafe extern "C-unwind" fn host_getTsc(host: *const Host) -> *const Tsc {
1018 let hostrc = unsafe { host.as_ref().unwrap() };
1019 hostrc.tsc()
1020 }
1021
1022 #[unsafe(no_mangle)]
1023 pub unsafe extern "C-unwind" fn host_getName(hostrc: *const Host) -> *const c_char {
1024 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1025 hostrc.params.hostname.as_ptr()
1026 }
1027
1028 #[unsafe(no_mangle)]
1029 pub unsafe extern "C-unwind" fn host_getDefaultIP(hostrc: *const Host) -> in_addr_t {
1030 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1031 let ip = hostrc.default_ip();
1032 u32::from(ip).to_be()
1033 }
1034
1035 #[unsafe(no_mangle)]
1036 pub unsafe extern "C-unwind" fn host_getNextPacketPriority(
1037 hostrc: *const Host,
1038 ) -> FifoPacketPriority {
1039 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1040 hostrc.get_next_packet_priority()
1041 }
1042
1043 #[unsafe(no_mangle)]
1044 pub unsafe extern "C-unwind" fn host_autotuneReceiveBuffer(hostrc: *const Host) -> bool {
1045 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1046 hostrc.params.autotune_recv_buf
1047 }
1048
1049 #[unsafe(no_mangle)]
1050 pub unsafe extern "C-unwind" fn host_autotuneSendBuffer(hostrc: *const Host) -> bool {
1051 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1052 hostrc.params.autotune_send_buf
1053 }
1054
1055 #[unsafe(no_mangle)]
1056 pub unsafe extern "C-unwind" fn host_getConfiguredRecvBufSize(hostrc: *const Host) -> u64 {
1057 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1058 hostrc.params.init_sock_recv_buf_size
1059 }
1060
1061 #[unsafe(no_mangle)]
1062 pub unsafe extern "C-unwind" fn host_getConfiguredSendBufSize(hostrc: *const Host) -> u64 {
1063 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1064 hostrc.params.init_sock_send_buf_size
1065 }
1066
1067 #[unsafe(no_mangle)]
1068 pub unsafe extern "C-unwind" fn host_getUpstreamRouter(hostrc: *const Host) -> *mut Router {
1069 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1070 &mut *hostrc.upstream_router_borrow_mut()
1071 }
1072
1073 #[unsafe(no_mangle)]
1074 pub unsafe extern "C-unwind" fn host_get_bw_down_kiBps(hostrc: *const Host) -> u64 {
1075 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1076 hostrc.bw_down_kiBps()
1077 }
1078
1079 #[unsafe(no_mangle)]
1080 pub unsafe extern "C-unwind" fn host_get_bw_up_kiBps(hostrc: *const Host) -> u64 {
1081 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1082 hostrc.bw_up_kiBps()
1083 }
1084
1085 #[unsafe(no_mangle)]
1088 pub unsafe extern "C-unwind" fn host_getDataPath(hostrc: *const Host) -> *const c_char {
1089 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1090 hostrc.data_dir_path_cstring.as_ptr()
1091 }
1092
1093 #[unsafe(no_mangle)]
1094 pub unsafe extern "C-unwind" fn host_disassociateInterface(
1095 hostrc: *const Host,
1096 c_protocol: cshadow::ProtocolType,
1097 bind_ip: in_addr_t,
1098 bind_port: in_port_t,
1099 peer_ip: in_addr_t,
1100 peer_port: in_port_t,
1101 ) {
1102 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1103
1104 let bind_ip = Ipv4Addr::from(u32::from_be(bind_ip));
1105 let peer_ip = Ipv4Addr::from(u32::from_be(peer_ip));
1106 let bind_port = u16::from_be(bind_port);
1107 let peer_port = u16::from_be(peer_port);
1108
1109 let bind_addr = SocketAddrV4::new(bind_ip, bind_port);
1110 let peer_addr = SocketAddrV4::new(peer_ip, peer_port);
1111
1112 let protocol = IanaProtocol::from(c_protocol);
1113
1114 hostrc
1116 .net_ns
1117 .disassociate_interface(protocol, bind_addr, peer_addr);
1118 }
1119
1120 #[unsafe(no_mangle)]
1121 pub unsafe extern "C-unwind" fn host_getRandomFreePort(
1122 hostrc: *const Host,
1123 c_protocol: cshadow::ProtocolType,
1124 interface_ip: in_addr_t,
1125 peer_ip: in_addr_t,
1126 peer_port: in_port_t,
1127 ) -> in_port_t {
1128 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1129
1130 let interface_ip = Ipv4Addr::from(u32::from_be(interface_ip));
1131 let peer_addr = SocketAddrV4::new(
1132 Ipv4Addr::from(u32::from_be(peer_ip)),
1133 u16::from_be(peer_port),
1134 );
1135
1136 let protocol = IanaProtocol::from(c_protocol);
1137
1138 hostrc
1139 .net_ns
1140 .get_random_free_port(
1141 protocol,
1142 interface_ip,
1143 peer_addr,
1144 hostrc.random.borrow_mut().deref_mut(),
1145 )
1146 .unwrap_or(0)
1147 .to_be()
1148 }
1149
1150 #[unsafe(no_mangle)]
1156 pub unsafe extern "C-unwind" fn host_getFutexTable(hostrc: *const Host) -> *mut FutexTable {
1157 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1158 &mut *hostrc.futextable_borrow_mut()
1159 }
1160
1161 #[unsafe(no_mangle)]
1163 pub unsafe extern "C-unwind" fn host_getProcess(
1164 host: *const Host,
1165 virtual_pid: libc::pid_t,
1166 ) -> *const Process {
1167 let host = unsafe { host.as_ref().unwrap() };
1168 let virtual_pid = ProcessId::try_from(virtual_pid).unwrap();
1169 host.process_borrow(virtual_pid)
1170 .map(|x| std::ptr::from_ref(&*x.borrow(host.root())))
1171 .unwrap_or(std::ptr::null_mut())
1172 }
1173
1174 #[unsafe(no_mangle)]
1183 pub unsafe extern "C-unwind" fn host_getThread(
1184 host: *const Host,
1185 virtual_tid: libc::pid_t,
1186 ) -> *const Thread {
1187 let host = unsafe { host.as_ref().unwrap() };
1188 let tid = ThreadId::try_from(virtual_tid).unwrap();
1189 for process in host.processes.borrow().values() {
1190 let process = process.borrow(host.root());
1191 if let Some(thread) = process.thread_borrow(tid) {
1192 let thread = thread.borrow(host.root());
1203 return std::ptr::from_ref(&*thread);
1204 };
1205 }
1206 std::ptr::null_mut()
1207 }
1208
1209 #[unsafe(no_mangle)]
1221 pub unsafe extern "C-unwind" fn host_getShimShmemLock(
1222 hostrc: *const Host,
1223 ) -> *mut shim_shmem::export::ShimShmemHostLock {
1224 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1225 let mut opt_lock = hostrc.shim_shmem_lock.borrow_mut();
1226 let lock = opt_lock.as_mut().unwrap();
1227 unsafe { lock.get().as_mut().unwrap().deref_mut() }
1230 }
1231
1232 #[unsafe(no_mangle)]
1234 pub unsafe extern "C-unwind" fn host_lockShimShmemLock(hostrc: *const Host) {
1235 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1236 hostrc.lock_shmem()
1237 }
1238
1239 #[unsafe(no_mangle)]
1241 pub unsafe extern "C-unwind" fn host_unlockShimShmemLock(hostrc: *const Host) {
1242 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1243 hostrc.unlock_shmem()
1244 }
1245
1246 #[unsafe(no_mangle)]
1251 pub unsafe extern "C-unwind" fn host_getNextDeterministicSequenceValue(
1252 hostrc: *const Host,
1253 ) -> u64 {
1254 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1255 hostrc.get_next_deterministic_sequence_value()
1256 }
1257
1258 #[unsafe(no_mangle)]
1260 pub unsafe extern "C-unwind" fn host_scheduleTaskAtEmulatedTime(
1261 hostrc: *const Host,
1262 task: *mut TaskRef,
1263 time: CEmulatedTime,
1264 ) -> bool {
1265 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1266 let task = unsafe { task.as_ref().unwrap().clone() };
1267 let time = EmulatedTime::from_c_emutime(time).unwrap();
1268 hostrc.schedule_task_at_emulated_time(task, time)
1269 }
1270
1271 #[unsafe(no_mangle)]
1273 pub unsafe extern "C-unwind" fn host_scheduleTaskWithDelay(
1274 hostrc: *const Host,
1275 task: *mut TaskRef,
1276 delay: CSimulationTime,
1277 ) -> bool {
1278 let hostrc = unsafe { hostrc.as_ref().unwrap() };
1279 let task = unsafe { task.as_ref().unwrap().clone() };
1280 let delay = SimulationTime::from_c_simtime(delay).unwrap();
1281 hostrc.schedule_task_with_delay(task, delay)
1282 }
1283
1284 #[unsafe(no_mangle)]
1285 pub unsafe extern "C-unwind" fn host_rngDouble(host: *const Host) -> f64 {
1286 let host = unsafe { host.as_ref().unwrap() };
1287 host.random_mut().random()
1288 }
1289
1290 #[unsafe(no_mangle)]
1292 pub extern "C-unwind" fn host_rngNextNBytes(host: *const Host, buf: *mut u8, len: usize) {
1293 let host = unsafe { host.as_ref().unwrap() };
1294 let buf = unsafe { std::slice::from_raw_parts_mut(buf, len) };
1295 host.random_mut().fill_bytes(buf);
1296 }
1297
1298 #[unsafe(no_mangle)]
1299 pub extern "C-unwind" fn host_paramsCpuFrequencyHz(host: *const Host) -> u64 {
1300 let host = unsafe { host.as_ref().unwrap() };
1301 host.params.cpu_frequency
1302 }
1303
1304 #[unsafe(no_mangle)]
1305 pub extern "C-unwind" fn host_addDelayNanos(host: *const Host, delay_nanos: u64) {
1306 let host = unsafe { host.as_ref().unwrap() };
1307 let delay = Duration::from_nanos(delay_nanos);
1308 host.cpu.borrow_mut().add_delay(delay);
1309 }
1310
1311 #[unsafe(no_mangle)]
1312 pub unsafe extern "C-unwind" fn host_socketWantsToSend(
1313 hostrc: *const Host,
1314 socket: *const InetSocket,
1315 addr: in_addr_t,
1316 ) {
1317 let host = unsafe { hostrc.as_ref().unwrap() };
1318 let socket = unsafe { socket.as_ref().unwrap() };
1319 let addr = u32::from_be(addr).into();
1320 host.notify_socket_has_packets(addr, socket);
1321 }
1322
1323 #[unsafe(no_mangle)]
1324 pub unsafe extern "C-unwind" fn host_continue(
1325 host: *const Host,
1326 pid: libc::pid_t,
1327 tid: libc::pid_t,
1328 ) {
1329 let host = unsafe { host.as_ref().unwrap() };
1330 host.resume(pid.try_into().unwrap(), tid.try_into().unwrap())
1331 }
1332}