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