Skip to content

Commit 634a5fd

Browse files
authored
config: add a PortSet type (#1106)
This branch adds a `PortSet` type that's a simple wrapper around `std::collections::HashSet` but specialized for storing ports (`u16` values). The `PortSet` type overrides the default hasher so that we don't have to actually hash ports, and just use their numeric value.
1 parent 3d0c1cc commit 634a5fd

File tree

5 files changed

+68
-7
lines changed

5 files changed

+68
-7
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,7 @@ dependencies = [
705705
"linkerd-tracing",
706706
"linkerd-transport-header",
707707
"pin-project",
708+
"quickcheck",
708709
"regex",
709710
"serde_json",
710711
"thiserror",

linkerd/app/core/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,6 @@ features = [
8282

8383
[target.'cfg(target_os = "linux")'.dependencies]
8484
linkerd-system = { path = "../../system" }
85+
86+
[dev-dependencies]
87+
quickcheck = { version = "1", default-features = false }

linkerd/app/core/src/config.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ use crate::{
44
svc::Param,
55
transport::{Keepalive, ListenAddr},
66
};
7-
use std::time::Duration;
7+
use std::{
8+
collections::HashSet,
9+
hash::{BuildHasherDefault, Hasher},
10+
time::Duration,
11+
};
812

913
#[derive(Clone, Debug)]
1014
pub struct ServerConfig {
@@ -33,6 +37,19 @@ pub struct ProxyConfig {
3337
pub detect_protocol_timeout: Duration,
3438
}
3539

40+
/// A `HashSet` specialized for ports.
41+
///
42+
/// Because ports are `u16` values, this type avoids the overhead of actually
43+
/// hashing ports.
44+
pub type PortSet = HashSet<u16, BuildHasherDefault<PortHasher>>;
45+
46+
/// A hasher for ports.
47+
///
48+
/// Because ports are single `u16` values, we don't have to hash them; we can just use
49+
/// the integer values as hashes directly.
50+
#[derive(Default)]
51+
pub struct PortHasher(u16);
52+
3653
// === impl ServerConfig ===
3754

3855
impl Param<ListenAddr> for ServerConfig {
@@ -46,3 +63,43 @@ impl Param<Keepalive> for ServerConfig {
4663
self.keepalive
4764
}
4865
}
66+
67+
// === impl PortHasher ===
68+
69+
impl Hasher for PortHasher {
70+
fn write(&mut self, _: &[u8]) {
71+
unreachable!("hashing a `u16` calls `write_u16`");
72+
}
73+
74+
#[inline]
75+
fn write_u16(&mut self, port: u16) {
76+
self.0 = port;
77+
}
78+
79+
#[inline]
80+
fn finish(&self) -> u64 {
81+
self.0 as u64
82+
}
83+
}
84+
85+
#[cfg(test)]
86+
mod tests {
87+
use super::*;
88+
use quickcheck::*;
89+
90+
quickcheck! {
91+
fn portset_contains_all_ports(ports: Vec<u16>) -> bool {
92+
// Make a port set containing the generated port numbers.
93+
let portset = ports.iter().cloned().collect::<PortSet>();
94+
for port in ports {
95+
// If the port set doesn't contain one of the ports it was
96+
// created with, that's bad news!
97+
if !portset.contains(&port) {
98+
return false;
99+
}
100+
}
101+
102+
true
103+
}
104+
}
105+
}

linkerd/app/inbound/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,22 @@ use self::{
2323
target::{HttpAccept, TcpAccept},
2424
};
2525
use linkerd_app_core::{
26-
config::{ConnectConfig, ProxyConfig, ServerConfig},
26+
config::{ConnectConfig, PortSet, ProxyConfig, ServerConfig},
2727
detect, drain, io, metrics, profiles,
2828
proxy::tcp,
2929
serve, svc, tls,
3030
transport::{self, listen::Bind, ClientAddr, Local, OrigDstAddr, Remote, ServerAddr},
3131
Error, NameMatch, Never, ProxyRuntime,
3232
};
33-
use std::{collections::HashSet, convert::TryFrom, fmt::Debug, future::Future, time::Duration};
33+
use std::{convert::TryFrom, fmt::Debug, future::Future, time::Duration};
3434
use tracing::{debug_span, info_span};
3535

3636
#[derive(Clone, Debug)]
3737
pub struct Config {
3838
pub allow_discovery: NameMatch,
3939
pub proxy: ProxyConfig,
4040
pub require_identity_for_inbound_ports: RequireIdentityForPorts,
41-
pub disable_protocol_detection_for_ports: HashSet<u16>,
41+
pub disable_protocol_detection_for_ports: PortSet,
4242
pub profile_idle_timeout: Duration,
4343
}
4444

linkerd/app/inbound/src/require_identity.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use crate::target::TcpAccept;
2-
use linkerd_app_core::{svc::stack::Predicate, tls, Conditional, Error};
3-
use std::{collections::HashSet, sync::Arc};
2+
use linkerd_app_core::{config::PortSet, svc::stack::Predicate, tls, Conditional, Error};
3+
use std::sync::Arc;
44
use thiserror::Error;
55

66
/// A connection policy that fails connections that don't have a client identity
77
/// if they target one of the configured local ports.
88
#[derive(Clone, Debug)]
99
pub struct RequireIdentityForPorts {
10-
ports: Arc<HashSet<u16>>,
10+
ports: Arc<PortSet>,
1111
}
1212

1313
#[derive(Debug, Error)]

0 commit comments

Comments
 (0)