Skip to content
Open
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
5 changes: 4 additions & 1 deletion ddm-admin-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ progenitor::generate_api!(
},
post_hook = (|log: &slog::Logger, result: &Result<_, _>| {
slog::trace!(log, "client response"; "result" => ?result);
})
}),
replace = {
Duration = std::time::Duration,
}
);

impl std::cmp::PartialEq for types::TunnelOrigin {
Expand Down
14 changes: 13 additions & 1 deletion ddm-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use ddm_types_versions::latest;
use ddm_types_versions::v1;
use dropshot::HttpError;
use dropshot::HttpResponseOk;
use dropshot::HttpResponseUpdatedNoContent;
Expand All @@ -26,6 +27,7 @@ api_versions!([
// | example for the next person.
// v
// (next_int, IDENT),
(2, PEER_DURATIONS),
(1, INITIAL),
]);

Expand All @@ -45,11 +47,21 @@ api_versions!([
pub trait DdmAdminApi {
type Context;

#[endpoint { method = GET, path = "/peers" }]
#[endpoint { method = GET, path = "/peers", versions = VERSION_PEER_DURATIONS.. }]
async fn get_peers(
ctx: RequestContext<Self::Context>,
) -> Result<HttpResponseOk<HashMap<u32, latest::db::PeerInfo>>, HttpError>;

#[endpoint { method = GET, path = "/peers", versions = ..VERSION_PEER_DURATIONS }]
async fn get_peers_v1(
ctx: RequestContext<Self::Context>,
) -> Result<HttpResponseOk<HashMap<u32, v1::db::PeerInfo>>, HttpError> {
let resp = Self::get_peers(ctx).await?;
let converted: HashMap<u32, v1::db::PeerInfo> =
resp.0.into_iter().map(|(k, v)| (k, v.into())).collect();
Ok(HttpResponseOk(converted))
}

#[endpoint { method = DELETE, path = "/peers/{addr}" }]
async fn expire_peer(
ctx: RequestContext<Self::Context>,
Expand Down
5 changes: 3 additions & 2 deletions ddm-types/versions/src/latest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ pub mod admin {
}

pub mod db {
pub use crate::v1::db::PeerInfo;
pub use crate::v1::db::PeerStatus;
pub use crate::v1::db::RouterKind;
pub use crate::v1::db::TunnelRoute;

pub use crate::v2::db::PeerInfo;
pub use crate::v2::db::PeerStatus;
}

pub mod exchange {
Expand Down
2 changes: 2 additions & 0 deletions ddm-types/versions/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,5 @@
pub mod latest;
#[path = "initial/mod.rs"]
pub mod v1;
#[path = "peer_durations/mod.rs"]
pub mod v2;
48 changes: 48 additions & 0 deletions ddm-types/versions/src/peer_durations/db.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use std::net::Ipv6Addr;
use std::time::Duration;

use crate::v1::db::RouterKind;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

/// Status of a DDM peer, including how long the peer has been in its
/// current state.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", content = "duration")]
pub enum PeerStatus {
Init(Duration),
Solicit(Duration),
Exchange(Duration),
Expired(Duration),
}

/// Information about a DDM peer.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct PeerInfo {
pub status: PeerStatus,
pub addr: Ipv6Addr,
pub host: String,
pub kind: RouterKind,
}

// Response backwards-compat: convert v2 PeerInfo to v1 PeerInfo.
impl From<PeerInfo> for crate::v1::db::PeerInfo {
fn from(value: PeerInfo) -> Self {
Self {
status: match value.status {
PeerStatus::Init(_) | PeerStatus::Solicit(_) => {
crate::v1::db::PeerStatus::NoContact
}
PeerStatus::Exchange(_) => crate::v1::db::PeerStatus::Active,
PeerStatus::Expired(_) => crate::v1::db::PeerStatus::Expired,
},
addr: value.addr,
host: value.host,
kind: value.kind,
}
}
}
10 changes: 10 additions & 0 deletions ddm-types/versions/src/peer_durations/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//! Version `PEER_DURATIONS` of the DDM Admin API.
//!
//! Tracks how long each DDM peer has been in its current state and exposes
//! that through the `/peers` endpoint with duration information.

pub mod db;
22 changes: 19 additions & 3 deletions ddm/src/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ use dropshot::HttpResponseUpdatedNoContent;
use dropshot::Path;
use dropshot::RequestContext;
use dropshot::TypedBody;
use mg_common::lock;
use mg_common::net::TunnelOrigin;
use mg_common::{lock, net::TunnelOrigin};
use oxnet::Ipv6Net;
use slog::{Logger, error, info};
use std::collections::{HashMap, HashSet};
Expand Down Expand Up @@ -113,7 +112,24 @@ impl DdmAdminApi for DdmAdminApiImpl {
ctx: RequestContext<Self::Context>,
) -> Result<HttpResponseOk<HashMap<u32, PeerInfo>>, HttpError> {
let ctx = lock!(ctx.context());
Ok(HttpResponseOk(ctx.db.peers()))
let mut result = HashMap::new();
for sm in &ctx.peers {
let if_index = *lock!(sm.iface.if_index);
let Some(peer) = lock!(sm.iface.peer_identity).clone() else {
continue;
};
let status = sm.iface.peer_status();
result.insert(
if_index,
PeerInfo {
status,
addr: peer.addr,
host: peer.hostname,
kind: peer.kind,
},
);
}
Ok(HttpResponseOk(result))
}

async fn expire_peer(
Expand Down
23 changes: 2 additions & 21 deletions ddm/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use ddm_types::db::{PeerInfo, TunnelRoute};
use mg_common::lock;
use mg_common::net::TunnelOrigin;
use ddm_types::db::TunnelRoute;
use mg_common::{lock, net::TunnelOrigin};
use oxnet::{IpNet, Ipv6Net};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -45,7 +44,6 @@ pub struct Db {

#[derive(Default, Clone)]
pub struct DbData {
pub peers: HashMap<u32, PeerInfo>,
pub imported: HashSet<Route>,
pub imported_tunnel: HashSet<TunnelRoute>,
}
Expand All @@ -65,10 +63,6 @@ impl Db {
lock!(self.data).clone()
}

pub fn peers(&self) -> HashMap<u32, PeerInfo> {
lock!(self.data).peers.clone()
}

pub fn imported(&self) -> HashSet<Route> {
lock!(self.data).imported.clone()
}
Expand Down Expand Up @@ -221,15 +215,6 @@ impl Db {
Ok(())
}

/// Set peer info at the given index. Returns true if peer information was
/// changed.
pub fn set_peer(&self, index: u32, info: PeerInfo) -> bool {
match lock!(self.data).peers.insert(index, info.clone()) {
Some(previous) => previous == info,
None => true,
}
}

pub fn remove_nexthop_routes(
&self,
nexthop: Ipv6Addr,
Expand Down Expand Up @@ -259,10 +244,6 @@ impl Db {
(removed, tnl_removed)
}

pub fn remove_peer(&self, index: u32) {
lock!(self.data).peers.remove(&index);
}

pub fn routes_by_vector(
&self,
dst: Ipv6Net,
Expand Down
33 changes: 16 additions & 17 deletions ddm/src/discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,12 @@
//! and 1 for a transit routers. The fourth byte is a hostname length followed
//! directly by a hostname of up to 255 bytes in length.

use crate::db::Db;
use crate::sm::{Config, Event, NeighborEvent, SessionStats};
use crate::sm::{
Config, Event, InterfaceState, NeighborEvent, PeerIdentity, SessionStats,
};
use crate::util::u8_slice_assume_init_ref;
use crate::{dbg, err, inf, trc, wrn};
use ddm_types::db::{PeerInfo, PeerStatus, RouterKind};
use ddm_types::db::RouterKind;
use mg_common::lock;
use serde::{Deserialize, Serialize};
use slog::Logger;
Expand Down Expand Up @@ -173,7 +174,7 @@ struct HandlerContext {
nbr: Arc<RwLock<Option<Neighbor>>>,
log: Logger,
event: Sender<Event>,
db: Db,
iface: Arc<InterfaceState>,
}

struct Neighbor {
Expand All @@ -187,7 +188,7 @@ pub(crate) fn handler(
hostname: String,
config: Config,
event: Sender<Event>,
db: Db,
iface: Arc<InterfaceState>,
stats: Arc<SessionStats>,
log: Logger,
) -> Result<(), DiscoveryError> {
Expand Down Expand Up @@ -227,7 +228,7 @@ pub(crate) fn handler(
hostname,
event,
config,
db,
iface,
};

let stop = Arc::new(AtomicBool::new(false));
Expand Down Expand Up @@ -519,17 +520,15 @@ fn handle_advertisement(
}
};
drop(guard);
let updated = ctx.db.set_peer(
ctx.config.if_index,
PeerInfo {
status: PeerStatus::Active,
addr: *sender,
host: hostname,
kind,
},
);
if updated {
lock!(stats.peer_address).replace(*sender);
let new_peer = PeerIdentity {
addr: *sender,
hostname,
kind,
};
let mut info = lock!(ctx.iface.peer_identity);
if info.as_ref() != Some(&new_peer) {
*info = Some(new_peer);
drop(info);
emit_nbr_update(ctx, sender, version);
}
}
Expand Down
Loading