1use std::borrow::Cow;
8use std::collections::HashMap;
9use std::future::Future;
10
11use cm_rust::NativeIntoFidl as _;
12use fidl::endpoints::{DiscoverableProtocolMarker as _, ServiceMarker};
13use fidl_fuchsia_component as fcomponent;
14use fidl_fuchsia_hardware_network as fhwnet;
15use fidl_fuchsia_net_debug as fnet_debug;
16use fidl_fuchsia_net_dhcp as fnet_dhcp;
17use fidl_fuchsia_net_dhcpv6 as fnet_dhcpv6;
18use fidl_fuchsia_net_filter as fnet_filter;
19use fidl_fuchsia_net_interfaces as fnet_interfaces;
20use fidl_fuchsia_net_interfaces_admin as fnet_interfaces_admin;
21use fidl_fuchsia_net_interfaces_ext as fnet_interfaces_ext;
22use fidl_fuchsia_net_masquerade as fnet_masquerade;
23use fidl_fuchsia_net_multicast_admin as fnet_multicast_admin;
24use fidl_fuchsia_net_name as fnet_name;
25use fidl_fuchsia_net_ndp as fnet_ndp;
26use fidl_fuchsia_net_neighbor as fnet_neighbor;
27use fidl_fuchsia_net_policy_properties as fnp_properties;
28use fidl_fuchsia_net_policy_socketproxy as fnp_socketproxy;
29use fidl_fuchsia_net_power as fnet_power;
30use fidl_fuchsia_net_reachability as fnet_reachability;
31use fidl_fuchsia_net_root as fnet_root;
32use fidl_fuchsia_net_routes as fnet_routes;
33use fidl_fuchsia_net_routes_admin as fnet_routes_admin;
34use fidl_fuchsia_net_settings as fnet_settings;
35use fidl_fuchsia_net_sockets as fnet_sockets;
36use fidl_fuchsia_net_stack as fnet_stack;
37use fidl_fuchsia_net_test_realm as fntr;
38use fidl_fuchsia_net_virtualization as fnet_virtualization;
39use fidl_fuchsia_netemul as fnetemul;
40use fidl_fuchsia_posix_socket as fposix_socket;
41use fidl_fuchsia_posix_socket_packet as fposix_socket_packet;
42use fidl_fuchsia_posix_socket_raw as fposix_socket_raw;
43use fidl_fuchsia_scheduler as fscheduler;
44use fidl_fuchsia_stash as fstash;
45use fidl_fuchsia_update_verify as fupdate_verify;
46
47use anyhow::Context as _;
48
49use crate::Result;
50
51#[derive(Copy, Clone, Eq, PartialEq, Debug)]
54#[allow(missing_docs)]
55pub enum NetstackVersion {
56 Netstack3,
57 ProdNetstack3,
58}
59
60impl NetstackVersion {
61 pub fn get_url(&self) -> &'static str {
63 match self {
64 NetstackVersion::Netstack3 => "#meta/netstack3-debug.cm",
65 NetstackVersion::ProdNetstack3 => "#meta/netstack3.cm",
66 }
67 }
68
69 pub fn get_services(&self) -> &[&'static str] {
71 macro_rules! common_services_and {
72 ($($name:expr),*) => {[
73 fnet_debug::InterfacesMarker::PROTOCOL_NAME,
74 fnet_interfaces_admin::InstallerMarker::PROTOCOL_NAME,
75 fnet_interfaces::StateMarker::PROTOCOL_NAME,
76 fnet_multicast_admin::Ipv4RoutingTableControllerMarker::PROTOCOL_NAME,
77 fnet_multicast_admin::Ipv6RoutingTableControllerMarker::PROTOCOL_NAME,
78 fnet_neighbor::ControllerMarker::PROTOCOL_NAME,
79 fnet_neighbor::ViewMarker::PROTOCOL_NAME,
80 fnet_root::InterfacesMarker::PROTOCOL_NAME,
81 fnet_root::RoutesV4Marker::PROTOCOL_NAME,
82 fnet_root::RoutesV6Marker::PROTOCOL_NAME,
83 fnet_routes::StateMarker::PROTOCOL_NAME,
84 fnet_routes::StateV4Marker::PROTOCOL_NAME,
85 fnet_routes::StateV6Marker::PROTOCOL_NAME,
86 fnet_routes_admin::RouteTableProviderV4Marker::PROTOCOL_NAME,
87 fnet_routes_admin::RouteTableProviderV6Marker::PROTOCOL_NAME,
88 fnet_routes_admin::RouteTableV4Marker::PROTOCOL_NAME,
89 fnet_routes_admin::RouteTableV6Marker::PROTOCOL_NAME,
90 fnet_routes_admin::RuleTableV4Marker::PROTOCOL_NAME,
91 fnet_routes_admin::RuleTableV6Marker::PROTOCOL_NAME,
92 fnet_stack::StackMarker::PROTOCOL_NAME,
93 fposix_socket_packet::ProviderMarker::PROTOCOL_NAME,
94 fposix_socket_raw::ProviderMarker::PROTOCOL_NAME,
95 fposix_socket::ProviderMarker::PROTOCOL_NAME,
96 fnet_debug::DiagnosticsMarker::PROTOCOL_NAME,
97 fnet_debug::PacketCaptureProviderMarker::PROTOCOL_NAME,
98
99 fupdate_verify::ComponentOtaHealthCheckMarker::PROTOCOL_NAME,
100 $($name),*
101 ]};
102 ($($name:expr),*,) => {common_services_and!($($name),*)}
104 }
105 match self {
106 NetstackVersion::Netstack3 | NetstackVersion::ProdNetstack3 => &common_services_and!(
107 fnet_filter::ControlMarker::PROTOCOL_NAME,
108 fnet_filter::StateMarker::PROTOCOL_NAME,
109 fnet_ndp::RouterAdvertisementOptionWatcherProviderMarker::PROTOCOL_NAME,
110 fnet_power::WakeGroupProviderMarker::PROTOCOL_NAME,
111 fnet_root::FilterMarker::PROTOCOL_NAME,
112 fnet_settings::StateMarker::PROTOCOL_NAME,
113 fnet_settings::ControlMarker::PROTOCOL_NAME,
114 fnet_sockets::DiagnosticsMarker::PROTOCOL_NAME,
115 fnet_sockets::ControlMarker::PROTOCOL_NAME,
116 ),
117 }
118 }
119}
120
121#[derive(Copy, Clone, Eq, PartialEq, Debug)]
123pub enum NetCfgVersion {
124 Basic,
126 Advanced,
128}
129
130#[derive(Copy, Clone, Eq, PartialEq, Debug)]
132pub enum ManagementAgent {
133 NetCfg(NetCfgVersion),
135}
136
137impl ManagementAgent {
138 pub fn get_url(&self) -> &'static str {
140 match self {
141 Self::NetCfg(NetCfgVersion::Basic) => constants::netcfg::basic::COMPONENT_URL,
142 Self::NetCfg(NetCfgVersion::Advanced) => constants::netcfg::advanced::COMPONENT_URL,
143 }
144 }
145
146 pub fn get_program_args(&self) -> &[&'static str] {
149 match self {
150 Self::NetCfg(NetCfgVersion::Basic) | Self::NetCfg(NetCfgVersion::Advanced) => {
151 &["--min-severity", "DEBUG"]
152 }
153 }
154 }
155
156 pub fn get_services(&self) -> &[&'static str] {
158 match self {
159 Self::NetCfg(NetCfgVersion::Basic) => &[
160 fnet_dhcpv6::PrefixProviderMarker::PROTOCOL_NAME,
161 fnet_masquerade::FactoryMarker::PROTOCOL_NAME,
162 fnet_name::DnsServerWatcherMarker::PROTOCOL_NAME,
163 fnp_properties::NetworksMarker::PROTOCOL_NAME,
164 fnp_socketproxy::NetworkRegistryMarker::PROTOCOL_NAME,
165 fnp_properties::NetworkTokenResolverMarker::PROTOCOL_NAME,
166 fnet_reachability::MonitorMarker::PROTOCOL_NAME,
167 ],
168 Self::NetCfg(NetCfgVersion::Advanced) => &[
169 fnet_dhcpv6::PrefixProviderMarker::PROTOCOL_NAME,
170 fnet_masquerade::FactoryMarker::PROTOCOL_NAME,
171 fnet_name::DnsServerWatcherMarker::PROTOCOL_NAME,
172 fnet_virtualization::ControlMarker::PROTOCOL_NAME,
173 fnp_properties::NetworksMarker::PROTOCOL_NAME,
174 fnp_socketproxy::NetworkRegistryMarker::PROTOCOL_NAME,
175 fnp_properties::NetworkTokenResolverMarker::PROTOCOL_NAME,
176 fnet_reachability::MonitorMarker::PROTOCOL_NAME,
177 ],
178 }
179 }
180}
181
182#[derive(Clone, Eq, PartialEq, Debug)]
184#[allow(missing_docs)]
185pub enum ManagerConfig {
186 Empty,
187 Dhcpv6,
188 Forwarding,
189 AllDelegated,
190 IfacePrefix,
191 DuplicateNames,
192 EnableSocketProxy,
193 EnableSocketProxyAllDelegated,
194 PacketFilterEthernet,
195 PacketFilterWlan,
196 WithBlackhole,
197 AllInterfaceLocalDelegated,
198}
199
200impl ManagerConfig {
201 fn as_str(&self) -> &'static str {
202 match self {
203 ManagerConfig::Empty => "/pkg/netcfg/empty.json",
204 ManagerConfig::Dhcpv6 => "/pkg/netcfg/dhcpv6.json",
205 ManagerConfig::Forwarding => "/pkg/netcfg/forwarding.json",
206 ManagerConfig::AllDelegated => "/pkg/netcfg/all_delegated.json",
207 ManagerConfig::IfacePrefix => "/pkg/netcfg/iface_prefix.json",
208 ManagerConfig::DuplicateNames => "/pkg/netcfg/duplicate_names.json",
209 ManagerConfig::EnableSocketProxy => "/pkg/netcfg/enable_socket_proxy.json",
210 ManagerConfig::EnableSocketProxyAllDelegated => {
211 "/pkg/netcfg/enable_socket_proxy_all_delegated.json"
212 }
213 ManagerConfig::PacketFilterEthernet => "/pkg/netcfg/packet_filter_ethernet.json",
214 ManagerConfig::PacketFilterWlan => "/pkg/netcfg/packet_filter_wlan.json",
215 ManagerConfig::WithBlackhole => "/pkg/netcfg/with_blackhole.json",
216 ManagerConfig::AllInterfaceLocalDelegated => {
217 "/pkg/netcfg/all_interface_local_delegated.json"
218 }
219 }
220 }
221}
222
223#[derive(Copy, Clone, Default, Eq, PartialEq, Debug)]
224pub enum SocketProxyType {
226 #[default]
227 None,
229 Real,
231 Fake,
233}
234
235impl SocketProxyType {
236 pub fn known_service_provider(&self) -> Option<KnownServiceProvider> {
238 match self {
239 SocketProxyType::None => None,
240 SocketProxyType::Real => Some(KnownServiceProvider::SocketProxy),
241 SocketProxyType::Fake => Some(KnownServiceProvider::FakeSocketProxy),
242 }
243 }
244}
245
246#[derive(Clone, Eq, PartialEq, Debug)]
248#[allow(missing_docs)]
249pub enum KnownServiceProvider {
250 Netstack(NetstackVersion),
251 Manager {
252 agent: ManagementAgent,
253 config: ManagerConfig,
254 use_dhcp_server: bool,
255 socket_proxy_type: SocketProxyType,
256 },
257 SecureStash,
258 DhcpServer {
259 persistent: bool,
260 },
261 DhcpClient,
262 Dhcpv6Client,
263 DnsResolver,
264 Reachability {
265 eager: bool,
266 },
267 SocketProxy,
268 NetworkTestRealm {
269 require_outer_netstack: bool,
270 },
271 FakeClock,
272 FakeSocketProxy,
273 FakeNetcfg,
274}
275
276#[allow(missing_docs)]
279pub mod constants {
280 pub mod netstack {
281 pub const COMPONENT_NAME: &str = "netstack";
282 }
283 pub mod netcfg {
284 pub const COMPONENT_NAME: &str = "netcfg";
285 pub mod basic {
286 pub const COMPONENT_URL: &str = "#meta/netcfg-basic.cm";
287 }
288 pub mod advanced {
289 pub const COMPONENT_URL: &str = "#meta/netcfg-advanced.cm";
290 }
291 pub mod fake {
292 pub const COMPONENT_URL: &str = "#meta/fake_netcfg.cm";
293 }
294 pub const DEV_CLASS_NETWORK: &str = "dev-class-network";
297 pub const CLASS_NETWORK_PATH: &str = "class/network";
298 }
299 pub mod socket_proxy {
300 pub const COMPONENT_NAME: &str = "network-socket-proxy";
301 pub const COMPONENT_URL: &str = "#meta/network-socket-proxy.cm";
302 }
303 pub mod secure_stash {
304 pub const COMPONENT_NAME: &str = "stash_secure";
305 pub const COMPONENT_URL: &str = "#meta/stash_secure.cm";
306 }
307 pub mod dhcp_server {
308 pub const COMPONENT_NAME: &str = "dhcpd";
309 pub const COMPONENT_URL: &str = "#meta/dhcpv4_server.cm";
310 }
311 pub mod dhcp_client {
312 pub const COMPONENT_NAME: &str = "dhcp-client";
313 pub const COMPONENT_URL: &str = "#meta/dhcp-client.cm";
314 }
315 pub mod dhcpv6_client {
316 pub const COMPONENT_NAME: &str = "dhcpv6-client";
317 pub const COMPONENT_URL: &str = "#meta/dhcpv6-client.cm";
318 }
319 pub mod dns_resolver {
320 pub const COMPONENT_NAME: &str = "dns_resolver";
321 pub const COMPONENT_URL: &str = "#meta/dns_resolver_with_fake_time.cm";
322 }
323 pub mod reachability {
324 pub const COMPONENT_NAME: &str = "reachability";
325 pub const COMPONENT_URL: &str = "#meta/reachability_with_fake_time.cm";
326 }
327 pub mod network_test_realm {
328 pub const COMPONENT_NAME: &str = "controller";
329 pub const COMPONENT_URL: &str = "#meta/controller.cm";
330 }
331 pub mod fake_clock {
332 pub const COMPONENT_NAME: &str = "fake_clock";
333 pub const COMPONENT_URL: &str = "#meta/fake_clock.cm";
334 }
335 pub mod fake_socket_proxy {
336 pub const COMPONENT_NAME: &str = "fake_socket_proxy";
337 pub const COMPONENT_URL: &str = "#meta/fake_socket_proxy.cm";
338 }
339}
340
341fn protocol_dep<P>(component_name: &'static str) -> fnetemul::ChildDep
342where
343 P: fidl::endpoints::DiscoverableProtocolMarker,
344{
345 fnetemul::ChildDep {
346 name: Some(component_name.into()),
347 capability: Some(fnetemul::ExposedCapability::Protocol(P::PROTOCOL_NAME.to_string())),
348 ..Default::default()
349 }
350}
351
352fn or_void_protocol_dep<P>(
353 component_name: &'static str,
354 is_child_present: bool,
355) -> fnetemul::ChildDep
356where
357 P: fidl::endpoints::DiscoverableProtocolMarker,
358{
359 if is_child_present { protocol_dep::<P>(component_name) } else { void_protocol_dep::<P>() }
360}
361
362fn void_protocol_dep<P>() -> fnetemul::ChildDep
363where
364 P: fidl::endpoints::DiscoverableProtocolMarker,
365{
366 fnetemul::ChildDep {
367 name: None,
368 capability: Some(fnetemul::ExposedCapability::Protocol(P::PROTOCOL_NAME.to_string())),
369 ..Default::default()
370 }
371}
372
373impl From<KnownServiceProvider> for fnetemul::ChildDef {
374 fn from(s: KnownServiceProvider) -> Self {
375 (&s).into()
376 }
377}
378
379impl<'a> From<&'a KnownServiceProvider> for fnetemul::ChildDef {
380 fn from(s: &'a KnownServiceProvider) -> Self {
381 match s {
382 KnownServiceProvider::Netstack(version) => fnetemul::ChildDef {
383 name: Some(constants::netstack::COMPONENT_NAME.to_string()),
384 source: Some(fnetemul::ChildSource::Component(version.get_url().to_string())),
385 exposes: Some(
386 version.get_services().iter().map(|service| service.to_string()).collect(),
387 ),
388 uses: {
389 let uses = vec![
390 fnetemul::Capability::LogSink(fnetemul::Empty {}),
391 fnetemul::Capability::TracingProvider(fnetemul::Empty),
392 fnetemul::Capability::StorageDep(fnetemul::StorageDep {
393 variant: Some(fnetemul::StorageVariant::Data),
394 path: Some("/data".to_string()),
395 ..Default::default()
396 }),
397 ];
398 Some(fnetemul::ChildUses::Capabilities(uses))
399 },
400 ..Default::default()
401 },
402 KnownServiceProvider::Manager {
403 agent,
404 use_dhcp_server,
405 config,
406 socket_proxy_type: _,
407 } => {
408 let enable_dhcpv6 = match config {
409 ManagerConfig::Dhcpv6 => true,
410 ManagerConfig::Forwarding
411 | ManagerConfig::Empty
412 | ManagerConfig::AllDelegated
413 | ManagerConfig::IfacePrefix
414 | ManagerConfig::DuplicateNames
415 | ManagerConfig::EnableSocketProxy
416 | ManagerConfig::EnableSocketProxyAllDelegated
417 | ManagerConfig::PacketFilterEthernet
418 | ManagerConfig::PacketFilterWlan
419 | ManagerConfig::WithBlackhole
420 | ManagerConfig::AllInterfaceLocalDelegated => false,
421 };
422
423 fnetemul::ChildDef {
424 name: Some(constants::netcfg::COMPONENT_NAME.to_string()),
425 source: Some(fnetemul::ChildSource::Component(agent.get_url().to_string())),
426 program_args: Some(
427 agent
428 .get_program_args()
429 .iter()
430 .cloned()
431 .chain(std::iter::once("--config-data"))
432 .chain(std::iter::once(config.as_str()))
433 .map(Into::into)
434 .collect(),
435 ),
436 exposes: Some(
437 agent.get_services().iter().map(|service| service.to_string()).collect(),
438 ),
439 uses: Some(fnetemul::ChildUses::Capabilities(
440 std::iter::once(fnetemul::Capability::ChildDep(or_void_protocol_dep::<
441 fnet_dhcp::Server_Marker,
442 >(
443 constants::dhcp_server::COMPONENT_NAME,
444 *use_dhcp_server,
445 )))
446 .chain(std::iter::once(fnetemul::Capability::ChildDep(
447 or_void_protocol_dep::<fnet_dhcpv6::ClientProviderMarker>(
448 constants::dhcpv6_client::COMPONENT_NAME,
449 enable_dhcpv6,
450 ),
451 )))
452 .chain(
453 [
454 fnetemul::Capability::LogSink(fnetemul::Empty {}),
455 fnetemul::Capability::ChildDep(protocol_dep::<
456 fnet_dhcp::ClientProviderMarker,
457 >(
458 constants::dhcp_client::COMPONENT_NAME,
459 )),
460 fnetemul::Capability::ChildDep(protocol_dep::<
461 fnet_filter::ControlMarker,
462 >(
463 constants::netstack::COMPONENT_NAME,
464 )),
465 fnetemul::Capability::ChildDep(protocol_dep::<
466 fnet_interfaces::StateMarker,
467 >(
468 constants::netstack::COMPONENT_NAME,
469 )),
470 fnetemul::Capability::ChildDep(protocol_dep::<
471 fnet_interfaces_admin::InstallerMarker,
472 >(
473 constants::netstack::COMPONENT_NAME,
474 )),
475 fnetemul::Capability::ChildDep(protocol_dep::<
476 fnet_stack::StackMarker,
477 >(
478 constants::netstack::COMPONENT_NAME,
479 )),
480 fnetemul::Capability::ChildDep(protocol_dep::<
481 fnet_routes_admin::RouteTableV4Marker,
482 >(
483 constants::netstack::COMPONENT_NAME,
484 )),
485 fnetemul::Capability::ChildDep(protocol_dep::<
486 fnet_routes_admin::RouteTableV6Marker,
487 >(
488 constants::netstack::COMPONENT_NAME,
489 )),
490 fnetemul::Capability::ChildDep(protocol_dep::<
491 fnet_routes_admin::RuleTableV4Marker,
492 >(
493 constants::netstack::COMPONENT_NAME,
494 )),
495 fnetemul::Capability::ChildDep(protocol_dep::<
496 fnet_routes_admin::RuleTableV6Marker,
497 >(
498 constants::netstack::COMPONENT_NAME,
499 )),
500 fnetemul::Capability::ChildDep(protocol_dep::<
501 fnet_name::LookupAdminMarker,
502 >(
503 constants::dns_resolver::COMPONENT_NAME,
504 )),
505 fnetemul::Capability::ChildDep(protocol_dep::<
506 fnet_ndp::RouterAdvertisementOptionWatcherProviderMarker,
507 >(
508 constants::netstack::COMPONENT_NAME,
509 )),
510 fnetemul::Capability::ChildDep(fnetemul::ChildDep {
511 name: Some(
512 fnetemul::NETEMUL_SERVICES_COMPONENT_NAME.to_string(),
513 ),
514 capability: Some(fnetemul::ExposedCapability::Service(
515 fhwnet::ServiceMarker::SERVICE_NAME.to_string(),
516 )),
517 ..Default::default()
518 }),
519 fnetemul::Capability::StorageDep(fnetemul::StorageDep {
520 variant: Some(fnetemul::StorageVariant::Data),
521 path: Some("/data".to_string()),
522 ..Default::default()
523 }),
524 ]
525 .into_iter(),
526 )
527 .collect(),
528 )),
529 eager: Some(true),
530 ..Default::default()
531 }
532 }
533 KnownServiceProvider::SecureStash => fnetemul::ChildDef {
534 name: Some(constants::secure_stash::COMPONENT_NAME.to_string()),
535 source: Some(fnetemul::ChildSource::Component(
536 constants::secure_stash::COMPONENT_URL.to_string(),
537 )),
538 exposes: Some(vec![fstash::SecureStoreMarker::PROTOCOL_NAME.to_string()]),
539 uses: Some(fnetemul::ChildUses::Capabilities(vec![
540 fnetemul::Capability::LogSink(fnetemul::Empty {}),
541 fnetemul::Capability::StorageDep(fnetemul::StorageDep {
542 variant: Some(fnetemul::StorageVariant::Data),
543 path: Some("/data".to_string()),
544 ..Default::default()
545 }),
546 ])),
547 ..Default::default()
548 },
549 KnownServiceProvider::DhcpServer { persistent } => fnetemul::ChildDef {
550 name: Some(constants::dhcp_server::COMPONENT_NAME.to_string()),
551 source: Some(fnetemul::ChildSource::Component(
552 constants::dhcp_server::COMPONENT_URL.to_string(),
553 )),
554 exposes: Some(vec![fnet_dhcp::Server_Marker::PROTOCOL_NAME.to_string()]),
555 uses: Some(fnetemul::ChildUses::Capabilities(
556 [
557 fnetemul::Capability::LogSink(fnetemul::Empty {}),
558 fnetemul::Capability::ChildDep(protocol_dep::<
559 fnet_neighbor::ControllerMarker,
560 >(
561 constants::netstack::COMPONENT_NAME
562 )),
563 fnetemul::Capability::ChildDep(
564 protocol_dep::<fposix_socket::ProviderMarker>(
565 constants::netstack::COMPONENT_NAME,
566 ),
567 ),
568 fnetemul::Capability::ChildDep(protocol_dep::<
569 fposix_socket_packet::ProviderMarker,
570 >(
571 constants::netstack::COMPONENT_NAME
572 )),
573 ]
574 .into_iter()
575 .chain(persistent.then_some(fnetemul::Capability::ChildDep(protocol_dep::<
576 fstash::SecureStoreMarker,
577 >(
578 constants::secure_stash::COMPONENT_NAME,
579 ))))
580 .collect(),
581 )),
582 program_args: if *persistent {
583 Some(vec![String::from("--persistent")])
584 } else {
585 None
586 },
587 ..Default::default()
588 },
589 KnownServiceProvider::DhcpClient => fnetemul::ChildDef {
590 name: Some(constants::dhcp_client::COMPONENT_NAME.to_string()),
591 source: Some(fnetemul::ChildSource::Component(
592 constants::dhcp_client::COMPONENT_URL.to_string(),
593 )),
594 exposes: Some(vec![fnet_dhcp::ClientProviderMarker::PROTOCOL_NAME.to_string()]),
595 uses: Some(fnetemul::ChildUses::Capabilities(vec![
596 fnetemul::Capability::LogSink(fnetemul::Empty {}),
597 fnetemul::Capability::ChildDep(protocol_dep::<fposix_socket::ProviderMarker>(
598 constants::netstack::COMPONENT_NAME,
599 )),
600 fnetemul::Capability::ChildDep(protocol_dep::<
601 fposix_socket_packet::ProviderMarker,
602 >(
603 constants::netstack::COMPONENT_NAME
604 )),
605 ])),
606 program_args: None,
607 ..Default::default()
608 },
609 KnownServiceProvider::Dhcpv6Client => fnetemul::ChildDef {
610 name: Some(constants::dhcpv6_client::COMPONENT_NAME.to_string()),
611 source: Some(fnetemul::ChildSource::Component(
612 constants::dhcpv6_client::COMPONENT_URL.to_string(),
613 )),
614 exposes: Some(vec![fnet_dhcpv6::ClientProviderMarker::PROTOCOL_NAME.to_string()]),
615 uses: Some(fnetemul::ChildUses::Capabilities(vec![
616 fnetemul::Capability::LogSink(fnetemul::Empty {}),
617 fnetemul::Capability::ChildDep(protocol_dep::<fposix_socket::ProviderMarker>(
618 constants::netstack::COMPONENT_NAME,
619 )),
620 ])),
621 ..Default::default()
622 },
623 KnownServiceProvider::DnsResolver => fnetemul::ChildDef {
624 name: Some(constants::dns_resolver::COMPONENT_NAME.to_string()),
625 source: Some(fnetemul::ChildSource::Component(
626 constants::dns_resolver::COMPONENT_URL.to_string(),
627 )),
628 exposes: Some(vec![
629 fnet_name::LookupAdminMarker::PROTOCOL_NAME.to_string(),
630 fnet_name::LookupMarker::PROTOCOL_NAME.to_string(),
631 ]),
632 uses: Some(fnetemul::ChildUses::Capabilities(vec![
633 fnetemul::Capability::LogSink(fnetemul::Empty {}),
634 fnetemul::Capability::ChildDep(protocol_dep::<fnet_routes::StateMarker>(
635 constants::netstack::COMPONENT_NAME,
636 )),
637 fnetemul::Capability::ChildDep(protocol_dep::<fposix_socket::ProviderMarker>(
638 constants::netstack::COMPONENT_NAME,
639 )),
640 fnetemul::Capability::ChildDep(protocol_dep::<
641 fidl_fuchsia_testing::FakeClockMarker,
642 >(
643 constants::fake_clock::COMPONENT_NAME
644 )),
645 fnetemul::Capability::ChildDep(void_protocol_dep::<
646 fscheduler::RoleManagerMarker,
647 >()),
648 ])),
649 ..Default::default()
650 },
651 KnownServiceProvider::Reachability { eager } => fnetemul::ChildDef {
652 name: Some(constants::reachability::COMPONENT_NAME.to_string()),
653 source: Some(fnetemul::ChildSource::Component(
654 constants::reachability::COMPONENT_URL.to_string(),
655 )),
656 exposes: Some(vec![fnet_reachability::MonitorMarker::PROTOCOL_NAME.to_string()]),
657 uses: Some(fnetemul::ChildUses::Capabilities(vec![
658 fnetemul::Capability::LogSink(fnetemul::Empty {}),
659 fnetemul::Capability::ChildDep(protocol_dep::<fnet_interfaces::StateMarker>(
660 constants::netstack::COMPONENT_NAME,
661 )),
662 fnetemul::Capability::ChildDep(protocol_dep::<fposix_socket::ProviderMarker>(
663 constants::netstack::COMPONENT_NAME,
664 )),
665 fnetemul::Capability::ChildDep(protocol_dep::<fnet_name::LookupMarker>(
666 constants::dns_resolver::COMPONENT_NAME,
667 )),
668 fnetemul::Capability::ChildDep(protocol_dep::<fnet_neighbor::ViewMarker>(
669 constants::netstack::COMPONENT_NAME,
670 )),
671 fnetemul::Capability::ChildDep(protocol_dep::<fnet_debug::InterfacesMarker>(
672 constants::netstack::COMPONENT_NAME,
673 )),
674 fnetemul::Capability::ChildDep(protocol_dep::<fnet_root::InterfacesMarker>(
675 constants::netstack::COMPONENT_NAME,
676 )),
677 fnetemul::Capability::ChildDep(protocol_dep::<fnet_routes::StateV4Marker>(
678 constants::netstack::COMPONENT_NAME,
679 )),
680 fnetemul::Capability::ChildDep(protocol_dep::<fnet_routes::StateV6Marker>(
681 constants::netstack::COMPONENT_NAME,
682 )),
683 fnetemul::Capability::ChildDep(protocol_dep::<fnet_debug::DiagnosticsMarker>(
684 constants::netstack::COMPONENT_NAME,
685 )),
686 fnetemul::Capability::ChildDep(protocol_dep::<
687 fidl_fuchsia_testing::FakeClockMarker,
688 >(
689 constants::fake_clock::COMPONENT_NAME
690 )),
691 ])),
692 eager: Some(*eager),
693 ..Default::default()
694 },
695 KnownServiceProvider::SocketProxy => fnetemul::ChildDef {
696 name: Some(constants::socket_proxy::COMPONENT_NAME.to_string()),
697 source: Some(fnetemul::ChildSource::Component(
698 constants::socket_proxy::COMPONENT_URL.to_string(),
699 )),
700 exposes: Some(vec![
701 fposix_socket::ProviderMarker::PROTOCOL_NAME.to_string(),
702 fposix_socket_raw::ProviderMarker::PROTOCOL_NAME.to_string(),
703 ]),
704 uses: Some(fnetemul::ChildUses::Capabilities(vec![
705 fnetemul::Capability::ChildDep(protocol_dep::<fposix_socket::ProviderMarker>(
706 constants::netstack::COMPONENT_NAME,
707 )),
708 fnetemul::Capability::ChildDep(
709 protocol_dep::<fposix_socket_raw::ProviderMarker>(
710 constants::netstack::COMPONENT_NAME,
711 ),
712 ),
713 fnetemul::Capability::ChildDep(fnetemul::ChildDep {
714 is_weak: Some(true),
715 ..protocol_dep::<fnp_properties::NetworksMarker>(
716 constants::netcfg::COMPONENT_NAME,
717 )
718 }),
719 ])),
720 ..Default::default()
721 },
722 KnownServiceProvider::NetworkTestRealm { require_outer_netstack } => {
723 fnetemul::ChildDef {
724 name: Some(constants::network_test_realm::COMPONENT_NAME.to_string()),
725 source: Some(fnetemul::ChildSource::Component(
726 constants::network_test_realm::COMPONENT_URL.to_string(),
727 )),
728 exposes: Some(vec![
729 fntr::ControllerMarker::PROTOCOL_NAME.to_string(),
730 fcomponent::RealmMarker::PROTOCOL_NAME.to_string(),
731 ]),
732 uses: Some(fnetemul::ChildUses::Capabilities(
733 [
734 fnetemul::Capability::LogSink(fnetemul::Empty {}),
735 fnetemul::Capability::ChildDep(fnetemul::ChildDep {
736 name: Some(fnetemul::NETEMUL_SERVICES_COMPONENT_NAME.to_string()),
737 capability: Some(fnetemul::ExposedCapability::Service(
738 fhwnet::ServiceMarker::SERVICE_NAME.to_string(),
739 )),
740 ..Default::default()
741 }),
742 ]
743 .into_iter()
744 .chain(
745 require_outer_netstack
746 .then_some([
747 fnetemul::Capability::ChildDep(protocol_dep::<
748 fnet_stack::StackMarker,
749 >(
750 constants::netstack::COMPONENT_NAME,
751 )),
752 fnetemul::Capability::ChildDep(protocol_dep::<
753 fnet_debug::InterfacesMarker,
754 >(
755 constants::netstack::COMPONENT_NAME,
756 )),
757 fnetemul::Capability::ChildDep(protocol_dep::<
758 fnet_root::InterfacesMarker,
759 >(
760 constants::netstack::COMPONENT_NAME,
761 )),
762 fnetemul::Capability::ChildDep(protocol_dep::<
763 fnet_interfaces::StateMarker,
764 >(
765 constants::netstack::COMPONENT_NAME,
766 )),
767 ])
768 .into_iter()
769 .flatten(),
770 )
771 .collect::<Vec<_>>(),
772 )),
773 ..Default::default()
774 }
775 }
776 KnownServiceProvider::FakeClock => fnetemul::ChildDef {
777 name: Some(constants::fake_clock::COMPONENT_NAME.to_string()),
778 source: Some(fnetemul::ChildSource::Component(
779 constants::fake_clock::COMPONENT_URL.to_string(),
780 )),
781 exposes: Some(vec![
782 fidl_fuchsia_testing::FakeClockMarker::PROTOCOL_NAME.to_string(),
783 fidl_fuchsia_testing::FakeClockControlMarker::PROTOCOL_NAME.to_string(),
784 ]),
785 uses: Some(fnetemul::ChildUses::Capabilities(vec![fnetemul::Capability::LogSink(
786 fnetemul::Empty {},
787 )])),
788 ..Default::default()
789 },
790 KnownServiceProvider::FakeSocketProxy => fnetemul::ChildDef {
791 name: Some(constants::fake_socket_proxy::COMPONENT_NAME.to_string()),
792 source: Some(fnetemul::ChildSource::Component(
793 constants::fake_socket_proxy::COMPONENT_URL.to_string(),
794 )),
795 exposes: Some(vec![
796 fnp_socketproxy::NetworkRegistryMarker::PROTOCOL_NAME.to_string(),
797 ]),
798 uses: Some(fnetemul::ChildUses::Capabilities(vec![
799 fnetemul::Capability::ChildDep(fnetemul::ChildDep {
800 is_weak: Some(true),
801 ..protocol_dep::<fnp_socketproxy::NetworkRegistryMarker>(
802 constants::netcfg::COMPONENT_NAME,
803 )
804 }),
805 ])),
806 ..Default::default()
807 },
808 KnownServiceProvider::FakeNetcfg => fnetemul::ChildDef {
809 name: Some(constants::netcfg::COMPONENT_NAME.to_string()),
810 source: Some(fnetemul::ChildSource::Component(
811 constants::netcfg::fake::COMPONENT_URL.to_string(),
812 )),
813 exposes: Some(vec![
814 fnp_properties::NetworksMarker::PROTOCOL_NAME.to_string(),
815 fnp_socketproxy::NetworkRegistryMarker::PROTOCOL_NAME.to_string(),
816 ]),
817 ..Default::default()
818 },
819 }
820 }
821}
822
823pub fn set_netstack3_opaque_iids(netstack: &mut fnetemul::ChildDef, value: bool) {
825 const KEY: &str = "opaque_iids";
826 set_structured_config_value(netstack, KEY.to_owned(), cm_rust::ConfigValue::from(value));
827}
828
829pub fn set_netstack3_suspend_enabled(netstack: &mut fnetemul::ChildDef, value: bool) {
831 const KEY: &str = "suspend_enabled";
832 set_structured_config_value(netstack, KEY.to_owned(), cm_rust::ConfigValue::from(value));
833}
834
835fn set_structured_config_value(
837 component: &mut fnetemul::ChildDef,
838 key: String,
839 value: cm_rust::ConfigValue,
840) {
841 component
842 .config_values
843 .get_or_insert_default()
844 .push(fnetemul::ChildConfigValue { key, value: value.native_into_fidl() });
845}
846
847pub trait Netstack: Copy + Clone {
849 const VERSION: NetstackVersion;
851}
852
853#[derive(Copy, Clone)]
856pub enum Netstack3 {}
857
858impl Netstack for Netstack3 {
859 const VERSION: NetstackVersion = NetstackVersion::Netstack3;
860}
861
862#[derive(Copy, Clone)]
865pub enum ProdNetstack3 {}
866
867impl Netstack for ProdNetstack3 {
868 const VERSION: NetstackVersion = NetstackVersion::ProdNetstack3;
869}
870
871pub trait Manager: Copy + Clone {
873 const MANAGEMENT_AGENT: ManagementAgent;
875}
876
877#[derive(Copy, Clone)]
879pub enum NetCfgBasic {}
880
881impl Manager for NetCfgBasic {
882 const MANAGEMENT_AGENT: ManagementAgent = ManagementAgent::NetCfg(NetCfgVersion::Basic);
883}
884
885#[derive(Copy, Clone)]
888pub enum NetCfgAdvanced {}
889
890impl Manager for NetCfgAdvanced {
891 const MANAGEMENT_AGENT: ManagementAgent = ManagementAgent::NetCfg(NetCfgVersion::Advanced);
892}
893
894pub trait TestSandboxExt {
896 fn create_netstack_realm<'a, N, S>(&'a self, name: S) -> Result<netemul::TestRealm<'a>>
898 where
899 N: Netstack,
900 S: Into<Cow<'a, str>>;
901
902 fn create_netstack_realm_with<'a, N, S, I>(
905 &'a self,
906 name: S,
907 children: I,
908 ) -> Result<netemul::TestRealm<'a>>
909 where
910 S: Into<Cow<'a, str>>,
911 N: Netstack,
912 I: IntoIterator,
913 I::Item: Into<fnetemul::ChildDef>;
914}
915
916impl TestSandboxExt for netemul::TestSandbox {
917 fn create_netstack_realm<'a, N, S>(&'a self, name: S) -> Result<netemul::TestRealm<'a>>
918 where
919 N: Netstack,
920 S: Into<Cow<'a, str>>,
921 {
922 self.create_netstack_realm_with::<N, _, _>(name, std::iter::empty::<fnetemul::ChildDef>())
923 }
924
925 fn create_netstack_realm_with<'a, N, S, I>(
926 &'a self,
927 name: S,
928 children: I,
929 ) -> Result<netemul::TestRealm<'a>>
930 where
931 S: Into<Cow<'a, str>>,
932 N: Netstack,
933 I: IntoIterator,
934 I::Item: Into<fnetemul::ChildDef>,
935 {
936 self.create_realm(
937 name,
938 [KnownServiceProvider::Netstack(N::VERSION)]
939 .iter()
940 .map(fnetemul::ChildDef::from)
941 .chain(children.into_iter().map(Into::into)),
942 )
943 }
944}
945
946pub trait TestRealmExt {
948 fn loopback_properties(
951 &self,
952 ) -> impl Future<
953 Output = Result<Option<fnet_interfaces_ext::Properties<fnet_interfaces_ext::AllInterest>>>,
954 >;
955
956 fn interface_control(&self, id: u64) -> Result<fnet_interfaces_ext::admin::Control>;
963}
964
965impl TestRealmExt for netemul::TestRealm<'_> {
966 async fn loopback_properties(
967 &self,
968 ) -> Result<Option<fnet_interfaces_ext::Properties<fnet_interfaces_ext::AllInterest>>> {
969 let interface_state = self
970 .connect_to_protocol::<fnet_interfaces::StateMarker>()
971 .context("failed to connect to fuchsia.net.interfaces/State")?;
972
973 let properties = fnet_interfaces_ext::existing(
974 fnet_interfaces_ext::event_stream_from_state(&interface_state, Default::default())
975 .expect("create watcher event stream"),
976 HashMap::<u64, fnet_interfaces_ext::PropertiesAndState<(), _>>::new(),
977 )
978 .await
979 .context("failed to get existing interface properties from watcher")?
980 .into_iter()
981 .find_map(|(_id, properties_and_state): (u64, _)| {
982 let fnet_interfaces_ext::PropertiesAndState {
983 properties: properties @ fnet_interfaces_ext::Properties { port_class, .. },
984 state: (),
985 } = properties_and_state;
986 port_class.is_loopback().then_some(properties)
987 });
988 Ok(properties)
989 }
990
991 fn interface_control(&self, id: u64) -> Result<fnet_interfaces_ext::admin::Control> {
992 let root_control = self
993 .connect_to_protocol::<fnet_root::InterfacesMarker>()
994 .context("connect to protocol")?;
995
996 let (control, server) = fnet_interfaces_ext::admin::Control::create_endpoints()
997 .context("create Control proxy")?;
998 root_control.get_admin(id, server).context("get admin")?;
999 Ok(control)
1000 }
1001}