netstack_testing_common/
dhcpv4.rs1#![warn(missing_docs)]
9
10use std::ops::Range;
11
12use dhcpv4::protocol::IntoFidlExt as _;
13
14use futures::StreamExt as _;
15use net_declare::net::prefix_length_v4;
16use net_types::ip::{Ipv4, PrefixLength};
17
18pub struct TestConfig {
20 pub server_addr: fidl_fuchsia_net::Ipv4Address,
22
23 pub managed_addrs: dhcpv4::configuration::ManagedAddresses,
25}
26
27impl TestConfig {
28 pub const fn new(server_addr_offset: u8, pool_offsets: Range<u8>) -> Self {
32 const fn from_offset(offset: u8) -> std::net::Ipv4Addr {
33 std::net::Ipv4Addr::new(192, 168, 0, offset)
34 }
35
36 let Range { start, end } = pool_offsets;
37
38 let max_offset =
39 1u8 << 32u8.checked_sub(DEFAULT_TEST_ADDRESS_POOL_PREFIX_LENGTH.get()).unwrap();
40
41 assert!(
42 server_addr_offset < max_offset,
43 "server_addr_offset must fit within default address pool prefix"
44 );
45 assert!(pool_offsets.start < pool_offsets.end, "pool_offsets start must be less than end");
46 assert!(
47 pool_offsets.start < max_offset,
48 "pool_offsets.start must fit within default address pool prefix"
49 );
50 assert!(
51 pool_offsets.end < max_offset,
52 "pool_offsets.end must fit within default address pool prefix"
53 );
54
55 let server_addr =
56 fidl_fuchsia_net::Ipv4Address { addr: from_offset(server_addr_offset).octets() };
57 let pool_range_start = from_offset(start);
58 let pool_range_stop = from_offset(end);
59
60 Self {
61 server_addr,
62 managed_addrs: dhcpv4::configuration::ManagedAddresses {
63 mask: dhcpv4::configuration::SubnetMask::new(
64 DEFAULT_TEST_ADDRESS_POOL_PREFIX_LENGTH,
65 ),
66 pool_range_start,
67 pool_range_stop,
68 },
69 }
70 }
71
72 pub fn expected_acquired(&self) -> fidl_fuchsia_net::Subnet {
74 let Self {
75 server_addr: _,
76 managed_addrs:
77 dhcpv4::configuration::ManagedAddresses { mask, pool_range_start, pool_range_stop: _ },
78 } = self;
79 fidl_fuchsia_net::Subnet {
80 addr: fidl_fuchsia_net::IpAddress::Ipv4(pool_range_start.into_fidl()),
81 prefix_len: mask.ones(),
82 }
83 }
84
85 pub fn server_addr_with_prefix(&self) -> fidl_fuchsia_net::Ipv4AddressWithPrefix {
87 let Self {
88 server_addr,
89 managed_addrs:
90 dhcpv4::configuration::ManagedAddresses {
91 mask,
92 pool_range_start: _,
93 pool_range_stop: _,
94 },
95 } = self;
96 fidl_fuchsia_net::Ipv4AddressWithPrefix { addr: *server_addr, prefix_len: mask.ones() }
97 }
98
99 pub fn dhcp_parameters(&self) -> Vec<fidl_fuchsia_net_dhcp::Parameter> {
101 let Self { server_addr, managed_addrs } = self;
102 vec![
103 fidl_fuchsia_net_dhcp::Parameter::IpAddrs(vec![*server_addr]),
104 fidl_fuchsia_net_dhcp::Parameter::AddressPool(managed_addrs.into_fidl()),
105 ]
106 }
107}
108
109pub const DEFAULT_TEST_ADDRESS_POOL_PREFIX_LENGTH: PrefixLength<Ipv4> = prefix_length_v4!(25);
111
112pub const DEFAULT_TEST_CONFIG: TestConfig = TestConfig::new(1, 2..5);
114
115pub async fn set_server_settings(
117 dhcp_server: &fidl_fuchsia_net_dhcp::Server_Proxy,
118 parameters: impl IntoIterator<Item = fidl_fuchsia_net_dhcp::Parameter>,
119 options: impl IntoIterator<Item = fidl_fuchsia_net_dhcp::Option_>,
120) {
121 let parameters = futures::stream::iter(parameters.into_iter()).for_each_concurrent(
122 None,
123 |parameter| async move {
124 dhcp_server
125 .set_parameter(¶meter)
126 .await
127 .expect("failed to call dhcp/Server.SetParameter")
128 .map_err(zx::Status::from_raw)
129 .unwrap_or_else(|e| {
130 panic!("dhcp/Server.SetParameter({:?}) returned error: {:?}", parameter, e)
131 })
132 },
133 );
134 let options =
135 futures::stream::iter(options.into_iter()).for_each_concurrent(None, |option| async move {
136 dhcp_server
137 .set_option(&option)
138 .await
139 .expect("failed to call dhcp/Server.SetOption")
140 .map_err(zx::Status::from_raw)
141 .unwrap_or_else(|e| {
142 panic!("dhcp/Server.SetOption({:?}) returned error: {:?}", option, e)
143 })
144 });
145 let ((), ()) = futures::future::join(parameters, options).await;
146}