Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Ipv6Addr::is_benchmarking #86434

Merged
merged 2 commits into from
Oct 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions library/std/src/net/ip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,30 @@ impl IpAddr {
}
}

/// Returns [`true`] if this address is in a range designated for benchmarking.
///
/// See the documentation for [`Ipv4Addr::is_benchmarking()`] and
/// [`Ipv6Addr::is_benchmarking()`] for more details.
///
/// # Examples
///
/// ```
/// #![feature(ip)]
///
/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
///
/// assert_eq!(IpAddr::V4(Ipv4Addr::new(198, 19, 255, 255)).is_benchmarking(), true);
/// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0)).is_benchmarking(), true);
/// ```
#[unstable(feature = "ip", issue = "27709")]
#[inline]
pub const fn is_benchmarking(&self) -> bool {
match self {
IpAddr::V4(ip) => ip.is_benchmarking(),
IpAddr::V6(ip) => ip.is_benchmarking(),
}
}

/// Returns [`true`] if this address is an [`IPv4` address], and [`false`]
/// otherwise.
///
Expand Down Expand Up @@ -1370,6 +1394,28 @@ impl Ipv6Addr {
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
}

/// Returns [`true`] if this is an address reserved for benchmarking (`2001:2::/48`).
///
/// This property is defined in [IETF RFC 5180], where it is mistakenly specified as covering the range `2001:0200::/48`.
/// This is corrected in [IETF RFC Errata 1752] to `2001:0002::/48`.
///
/// [IETF RFC 5180]: https://tools.ietf.org/html/rfc5180
/// [IETF RFC Errata 1752]: https://www.rfc-editor.org/errata_search.php?eid=1752
///
/// ```
/// #![feature(ip)]
///
/// use std::net::Ipv6Addr;
///
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc613, 0x0).is_benchmarking(), false);
/// assert_eq!(Ipv6Addr::new(0x2001, 0x2, 0, 0, 0, 0, 0, 0).is_benchmarking(), true);
/// ```
#[unstable(feature = "ip", issue = "27709")]
#[inline]
pub const fn is_benchmarking(&self) -> bool {
(self.segments()[0] == 0x2001) && (self.segments()[1] == 0x2) && (self.segments()[2] == 0)
}

/// Returns [`true`] if the address is a globally routable unicast address.
///
/// The following return false:
Expand Down
89 changes: 57 additions & 32 deletions library/std/src/net/ip/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ fn ip_properties() {
let global: u8 = 1 << 2;
let multicast: u8 = 1 << 3;
let doc: u8 = 1 << 4;
let benchmarking: u8 = 1 << 5;

if ($mask & unspec) == unspec {
assert!(ip!($s).is_unspecified());
Expand Down Expand Up @@ -254,6 +255,12 @@ fn ip_properties() {
} else {
assert!(!ip!($s).is_documentation());
}

if ($mask & benchmarking) == benchmarking {
assert!(ip!($s).is_benchmarking());
} else {
assert!(!ip!($s).is_benchmarking());
}
}};
}

Expand All @@ -262,6 +269,7 @@ fn ip_properties() {
let global: u8 = 1 << 2;
let multicast: u8 = 1 << 3;
let doc: u8 = 1 << 4;
let benchmarking: u8 = 1 << 5;

check!("0.0.0.0", unspec);
check!("0.0.0.1");
Expand All @@ -280,9 +288,9 @@ fn ip_properties() {
check!("239.255.255.255", global | multicast);
check!("255.255.255.255");
// make sure benchmarking addresses are not global
check!("198.18.0.0");
check!("198.18.54.2");
check!("198.19.255.255");
check!("198.18.0.0", benchmarking);
check!("198.18.54.2", benchmarking);
check!("198.19.255.255", benchmarking);
// make sure addresses reserved for protocol assignment are not global
check!("192.0.0.0");
check!("192.0.0.255");
Expand Down Expand Up @@ -313,6 +321,7 @@ fn ip_properties() {
check!("ff08::", multicast);
check!("ff0e::", global | multicast);
check!("2001:db8:85a3::8a2e:370:7334", doc);
check!("2001:2::ac32:23ff:21", global | benchmarking);
Copy link
Contributor Author

@CDirkx CDirkx Jun 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the IANA IPv6 Special Address Registry benchmarking addresses are not globally reachable. However due to the current simplistic implementation of Ipv6Addr::is_global compared to Ipv4Addr::is_global, Rust currently considers benchmarking addresses global. I plan to address this in a future PR reworking is_global.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rework of Ipv6Addr::is_global has been submitted (#86634).

check!("102:304:506:708:90a:b0c:d0e:f10", global);
}

Expand Down Expand Up @@ -475,21 +484,22 @@ fn ipv6_properties() {
assert_eq!(&ip!($s).octets(), octets);
assert_eq!(Ipv6Addr::from(*octets), ip!($s));

let unspecified: u16 = 1 << 0;
let loopback: u16 = 1 << 1;
let unique_local: u16 = 1 << 2;
let global: u16 = 1 << 3;
let unicast_link_local: u16 = 1 << 4;
let unicast_global: u16 = 1 << 7;
let documentation: u16 = 1 << 8;
let multicast_interface_local: u16 = 1 << 9;
let multicast_link_local: u16 = 1 << 10;
let multicast_realm_local: u16 = 1 << 11;
let multicast_admin_local: u16 = 1 << 12;
let multicast_site_local: u16 = 1 << 13;
let multicast_organization_local: u16 = 1 << 14;
let multicast_global: u16 = 1 << 15;
let multicast: u16 = multicast_interface_local
let unspecified: u32 = 1 << 0;
let loopback: u32 = 1 << 1;
let unique_local: u32 = 1 << 2;
let global: u32 = 1 << 3;
let unicast_link_local: u32 = 1 << 4;
let unicast_global: u32 = 1 << 7;
let documentation: u32 = 1 << 8;
let benchmarking: u32 = 1 << 16;
let multicast_interface_local: u32 = 1 << 9;
let multicast_link_local: u32 = 1 << 10;
let multicast_realm_local: u32 = 1 << 11;
let multicast_admin_local: u32 = 1 << 12;
let multicast_site_local: u32 = 1 << 13;
let multicast_organization_local: u32 = 1 << 14;
let multicast_global: u32 = 1 << 15;
let multicast: u32 = multicast_interface_local
Comment on lines -478 to +502
Copy link
Contributor Author

@CDirkx CDirkx Jun 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More than 16 properties are now being checked, so the tag type is changed from u16 to u32. Also benchmarking is assigned value i << 16, the order doesn't really matter, only that the value is distinct from the other tags.

| multicast_admin_local
| multicast_global
| multicast_link_local
Expand Down Expand Up @@ -532,6 +542,11 @@ fn ipv6_properties() {
} else {
assert!(!ip!($s).is_documentation());
}
if ($mask & benchmarking) == benchmarking {
assert!(ip!($s).is_benchmarking());
} else {
assert!(!ip!($s).is_benchmarking());
}
if ($mask & multicast) != 0 {
assert!(ip!($s).multicast_scope().is_some());
assert!(ip!($s).is_multicast());
Expand Down Expand Up @@ -570,20 +585,21 @@ fn ipv6_properties() {
}
}

let unspecified: u16 = 1 << 0;
let loopback: u16 = 1 << 1;
let unique_local: u16 = 1 << 2;
let global: u16 = 1 << 3;
let unicast_link_local: u16 = 1 << 4;
let unicast_global: u16 = 1 << 7;
let documentation: u16 = 1 << 8;
let multicast_interface_local: u16 = 1 << 9;
let multicast_link_local: u16 = 1 << 10;
let multicast_realm_local: u16 = 1 << 11;
let multicast_admin_local: u16 = 1 << 12;
let multicast_site_local: u16 = 1 << 13;
let multicast_organization_local: u16 = 1 << 14;
let multicast_global: u16 = 1 << 15;
let unspecified: u32 = 1 << 0;
let loopback: u32 = 1 << 1;
let unique_local: u32 = 1 << 2;
let global: u32 = 1 << 3;
let unicast_link_local: u32 = 1 << 4;
let unicast_global: u32 = 1 << 7;
let documentation: u32 = 1 << 8;
let benchmarking: u32 = 1 << 16;
let multicast_interface_local: u32 = 1 << 9;
let multicast_link_local: u32 = 1 << 10;
let multicast_realm_local: u32 = 1 << 11;
let multicast_admin_local: u32 = 1 << 12;
let multicast_site_local: u32 = 1 << 13;
let multicast_organization_local: u32 = 1 << 14;
let multicast_global: u32 = 1 << 15;

check!("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unspecified);

Expand Down Expand Up @@ -679,6 +695,12 @@ fn ipv6_properties() {
documentation
);

check!(
"2001:2::ac32:23ff:21",
&[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21],
global | unicast_global | benchmarking
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, benchmarking addresses should not actually be globally reachable. They do however have global unicast scope.

);

check!(
"102:304:506:708:90a:b0c:d0e:f10",
&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
Expand Down Expand Up @@ -885,6 +907,9 @@ fn ipv6_const() {
const IS_DOCUMENTATION: bool = IP_ADDRESS.is_documentation();
assert!(!IS_DOCUMENTATION);

const IS_BENCHMARKING: bool = IP_ADDRESS.is_benchmarking();
assert!(!IS_BENCHMARKING);

const IS_UNICAST_GLOBAL: bool = IP_ADDRESS.is_unicast_global();
assert!(!IS_UNICAST_GLOBAL);

Expand Down