Skip to content

Commit b6b6c63

Browse files
[merge] merge main
2 parents 22503d6 + ce015cd commit b6b6c63

38 files changed

Lines changed: 3795 additions & 1861 deletions

Cargo.lock

Lines changed: 158 additions & 135 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,17 +98,17 @@ expectorate = "1.2.0"
9898
schemars = { version = "0.8.22", features = [ "uuid1", "chrono" ] }
9999
tokio = { version = "1.52.1", features = ["full"] }
100100
serde_repr = "0.1"
101-
anyhow = "1.0.103"
101+
anyhow = "1.0.104"
102102
port-file = "0.1.0"
103-
hyper = "1.10.1"
103+
hyper = "1.11.0"
104104
hyper-util = { version = "0.1", features = ["full"] }
105-
serde_json = "1.0.150"
105+
serde_json = "1.0.151"
106106
percent-encoding = "2.3.2"
107107
libnet = { git = "https://github.com/oxidecomputer/netadm-sys", branch = "main" }
108108
progenitor = "0.14"
109109
progenitor-client = "0.14"
110110
reqwest = { version = "0.13", default-features = false, features = ["json", "stream", "rustls"] }
111-
clap = { version = "4.6.1", features = ["derive", "unstable-styles", "env"] }
111+
clap = { version = "4.6.4", features = ["derive", "unstable-styles", "env"] }
112112
tabwriter = { version = "1", features = ["ansi_formatting"] }
113113
colored = "3.1"
114114
ztest = { git = "https://github.com/oxidecomputer/falcon", branch = "main" }
@@ -141,7 +141,8 @@ itertools = "0.15"
141141
rhai = { version = "1", features = ["metadata", "sync"] }
142142
semver = "1.0"
143143
proptest = "1.10"
144-
serial_test = "3.3"
144+
test-strategy = "0.4"
145+
serial_test = "4.0"
145146
internet-checksum = "0.2.1"
146147
network-interface = { git = "https://github.com/oxidecomputer/network-interface", branch = "illumos" }
147148
natord = "1.0"
@@ -150,12 +151,12 @@ iddqd = "0.4"
150151

151152
[workspace.dependencies.opte-ioctl]
152153
git = "https://github.com/oxidecomputer/opte"
153-
rev = "dfcf0663cfb90ea75e8ee5591b033d68ba6d9fcc"
154+
rev = "3ddd7e684a78ad33be66717408c381b1962ae04e"
154155

155156
[workspace.dependencies.oxide-vpc]
156157
git = "https://github.com/oxidecomputer/opte"
157-
rev = "dfcf0663cfb90ea75e8ee5591b033d68ba6d9fcc"
158+
rev = "3ddd7e684a78ad33be66717408c381b1962ae04e"
158159

159160
[workspace.dependencies.dpd-client]
160161
git = "https://github.com/oxidecomputer/dendrite"
161-
rev = "4871abc13ca21ee97c684f1d5ed363e8a86f3441"
162+
rev = "04a52a3240a26c58f03e1cf40353d67ff69d76b6"

bfd/Cargo.toml

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,17 @@ version = "0.1.0"
44
edition = "2024"
55

66
[dependencies]
7-
client-common.workspace = true
8-
rdb = { path = "../rdb" }
9-
mg-api-types.workspace = true
10-
mg-common.workspace = true
11-
slog.workspace = true
12-
slog-bunyan.workspace = true
13-
slog-async.workspace = true
14-
num_enum.workspace = true
157
anyhow.workspace = true
16-
schemars.workspace = true
17-
serde.workspace = true
8+
mg-common.workspace = true
9+
mg-api-types.workspace = true
1810
rand.workspace = true
11+
rdb.workspace = true
12+
slog.workspace = true
13+
slog-error-chain.workspace = true
14+
socket2.workspace = true
1915
thiserror.workspace = true
16+
tokio.workspace = true
2017

2118
[dev-dependencies]
22-
pretty_assertions.workspace = true
23-
anyhow.workspace = true
19+
proptest.workspace = true
20+
test-strategy.workspace = true

bfd/src/bidi.rs

Lines changed: 0 additions & 24 deletions
This file was deleted.

bfd/src/daemon.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
use crate::AddPeerError;
6+
use crate::AddPeerRequest;
7+
use crate::ListenerShutdownHandle;
8+
use crate::Session;
9+
use crate::SessionCounters;
10+
use crate::dispatcher::Dispatcher;
11+
use crate::egress_src_port_iter::EgressSrcPortIter;
12+
use slog::Logger;
13+
use slog::warn;
14+
use std::collections::HashMap;
15+
use std::collections::hash_map;
16+
use std::net::IpAddr;
17+
use std::net::SocketAddr;
18+
use std::sync::Arc;
19+
20+
pub struct Daemon {
21+
dispatcher: Dispatcher,
22+
sessions: HashMap<IpAddr, Session>,
23+
egress_src_port: Arc<EgressSrcPortIter>,
24+
log: Logger,
25+
}
26+
27+
impl Daemon {
28+
pub fn new(log: Logger) -> Self {
29+
Self::with_dispatcher(Dispatcher::new(), log)
30+
}
31+
32+
// Non-public method to allow construction with a custom dispatcher.
33+
//
34+
// This is used by tests when they want to use a `Dispatcher` with a custom
35+
// backend (e.g., so we can use nonstandard listening ports in tests).
36+
pub(crate) fn with_dispatcher(dispatcher: Dispatcher, log: Logger) -> Self {
37+
Self {
38+
sessions: HashMap::new(),
39+
dispatcher,
40+
egress_src_port: Arc::new(EgressSrcPortIter::new()),
41+
log,
42+
}
43+
}
44+
45+
pub fn sessions_iter(&self) -> hash_map::Iter<'_, IpAddr, Session> {
46+
self.sessions.iter()
47+
}
48+
49+
pub fn listen_addr_for_peer(&self, peer: &IpAddr) -> Option<SocketAddr> {
50+
self.dispatcher.listen_addr_for_peer(peer)
51+
}
52+
53+
pub fn add_peer(
54+
&mut self,
55+
db: rdb::Db,
56+
rq: AddPeerRequest,
57+
) -> Result<(), AddPeerError> {
58+
let peer = rq.remote_addr.ip();
59+
match self.sessions.entry(peer) {
60+
hash_map::Entry::Occupied(_) => {
61+
// TODO-correctness Currently clients have no way to update an
62+
// existing peer: they have to remove it and recreate it. This
63+
// needs work both here and in omicron to fix.
64+
// <https://github.com/oxidecomputer/omicron/issues/4921>
65+
warn!(
66+
self.log, "attempt to add peer that already exists";
67+
"component" => crate::COMPONENT_BFD,
68+
"module" => crate::MOD_DAEMON,
69+
"unit" => crate::UNIT_PEER,
70+
"peer" => %peer,
71+
);
72+
Err(AddPeerError::PeerExists(peer))
73+
}
74+
hash_map::Entry::Vacant(entry) => {
75+
let counters = Arc::new(SessionCounters::default());
76+
77+
// If `ensure` fails, we can immediately bail out. If it
78+
// succeeds, we've now modified state inside the dispatcher;
79+
// it's critical that `Session::new()` is infallible; if that
80+
// changes in the future, we need to be very careful to ensure
81+
// that we undo the dispatcher state change if we can't
82+
// successfully create the associated `Session`.
83+
let listener_rx = self.dispatcher.ensure(
84+
rq.listen_addr,
85+
peer,
86+
Arc::clone(&counters),
87+
&self.log,
88+
)?;
89+
90+
let session = Session::new(
91+
db,
92+
rq,
93+
counters,
94+
Arc::clone(&self.egress_src_port),
95+
listener_rx,
96+
&self.log,
97+
);
98+
99+
entry.insert(session);
100+
Ok(())
101+
}
102+
}
103+
}
104+
105+
pub fn remove_peer(
106+
&mut self,
107+
peer: IpAddr,
108+
) -> Option<ListenerShutdownHandle> {
109+
self.sessions.remove(&peer);
110+
self.dispatcher.remove(peer)
111+
}
112+
}

0 commit comments

Comments
 (0)