6b2bb3029b
* squashing feat: merge intermediate upgrade mode changes #6174 to more easily resolve merge conflicts during rebasing added additional v2 query for metadata endpoint for requesting upgrade mode recheck added additional message to v6 authenticator to request explicit upgrade mode recheck clippy test fixes due to updated keys updated assertion for upgrading v1 top up request to v2 compare attester public key against the expected value within the credential proxy use pre-generated attestation public keys within nym-nodes remove version deprecation bugfix: default bandwidth response for authenticator expose upgrade mode information in authenticator responses adding tests for new v2 server passing upgrade mode information in metadata endpoint v2 wireguard private metadata bugfix: make sure to immediately poll for attestation after spawning task fix gateway probe and remove code duplication for finalizing registration squashing before rebasing post rebasing fixes AuthenticatorVersion helpers additional nits allow unwraps in mocks fixed linux build clippy integrating upgrade mode into authenticator fixed build after adding wrappers to response types conditionally updating peer handle bandwidth cleanup negotiate initial protocol during registration change auth to use highest protocol handler for JWT message dont meter client bandwidth in upgrade mode handling recheck requests sending information about upgrade_mode on client messages gateway watching for upgrade mode attestation wip: gateways to disable bandwidth metering on upgrade mode * fixed ServerResponse deserialisation * fixed incorrect swagger path for upgrade mode check endpoint * moved upgrade mode endpoint out of bandwidth routes * chore: remove unused error variant * removed re-export of UpgradeModeAttestation from credentials-interface * chore: define single source of truth for minimum bandwidth threshold value * moved type definitions out of traits.rs * updated v6 versioning to point to niolo release instead * fixed incorrect error mapping
116 lines
3.9 KiB
Rust
116 lines
3.9 KiB
Rust
// Copyright 2024 - Nym Technologies SA <contact@nymtech.net>
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
use defguard_wireguard_rs::host::Peer;
|
|
use std::time::Duration;
|
|
|
|
const DEFAULT_PEER_MAX_FLUSHING_RATE: Duration = Duration::from_secs(60 * 60 * 24); // 24h
|
|
const DEFAULT_PEER_MAX_DELTA_FLUSHING_AMOUNT: u64 = 512 * 1024 * 1024; // 512MB
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct PeerFlushingBehaviourConfig {
|
|
/// Defines maximum delay between peer information being flushed to the persistent storage.
|
|
pub peer_max_flushing_rate: Duration,
|
|
|
|
/// Defines a maximum change in peer before it gets flushed to the persistent storage.
|
|
pub peer_max_delta_flushing_amount: u64,
|
|
}
|
|
|
|
impl Default for PeerFlushingBehaviourConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
peer_max_flushing_rate: DEFAULT_PEER_MAX_FLUSHING_RATE,
|
|
peer_max_delta_flushing_amount: DEFAULT_PEER_MAX_DELTA_FLUSHING_AMOUNT,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct CachedPeerManager {
|
|
pub(crate) peer_information: Option<PeerInformation>,
|
|
}
|
|
|
|
impl CachedPeerManager {
|
|
pub(crate) fn new(peer: &Peer) -> Self {
|
|
Self {
|
|
peer_information: Some(peer.into()),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn get_peer(&self) -> Option<PeerInformation> {
|
|
self.peer_information
|
|
}
|
|
|
|
pub(crate) fn remove_peer(&mut self) {
|
|
self.peer_information = None;
|
|
}
|
|
|
|
pub(crate) fn update(&mut self, kernel_peer: PeerInformation) {
|
|
if let Some(peer_information) = self.peer_information.as_mut() {
|
|
peer_information.update_tx_rx_bytes(kernel_peer);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub(crate) struct PeerInformation {
|
|
pub(crate) tx_bytes: u64,
|
|
pub(crate) rx_bytes: u64,
|
|
}
|
|
|
|
impl From<&Peer> for PeerInformation {
|
|
fn from(value: &Peer) -> Self {
|
|
Self {
|
|
tx_bytes: value.tx_bytes,
|
|
rx_bytes: value.rx_bytes,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PeerInformation {
|
|
pub(crate) fn update_tx_rx_bytes(&mut self, peer: PeerInformation) {
|
|
self.tx_bytes = peer.tx_bytes;
|
|
self.rx_bytes = peer.rx_bytes;
|
|
}
|
|
|
|
fn rx_tx_total(&self, typ: &'static str) -> Option<u64> {
|
|
self.rx_bytes.checked_add(self.tx_bytes).or_else(|| {
|
|
tracing::error!(
|
|
"overflow on {typ} adding bytes: {} + {}",
|
|
self.rx_bytes,
|
|
self.tx_bytes
|
|
);
|
|
None
|
|
})
|
|
}
|
|
|
|
/// Attempt to determine the amount of consumed bandwidth based on the current peer information
|
|
/// and state from the last checkpoint.
|
|
pub(crate) fn consumed_bandwidth(kernel: &Self, previous_cached: &Self) -> Option<u64> {
|
|
let kernel_total = kernel.rx_tx_total("kernel")?;
|
|
let cached_total = previous_cached.rx_tx_total("cached")?;
|
|
kernel_total.checked_sub(cached_total).or_else(|| {
|
|
tracing::error!("Overflow on spent bandwidth subtraction: kernel - cached = {kernel_total} - {cached_total}");
|
|
None
|
|
})
|
|
}
|
|
|
|
/// Attempt to determine the amount of consumed bandwidth based on the current peer information
|
|
/// and state from the last checkpoint.
|
|
/// On failures, it will attempt to default to most sensible alternative
|
|
///
|
|
/// Note, it is responsibility of the caller to ensure that `self` corresponds to the kernel peer information
|
|
pub(crate) fn consumed_kernel_bandwidth(&self, previous_cached: &Self) -> i64 {
|
|
let Some(consumed) = Self::consumed_bandwidth(self, previous_cached) else {
|
|
// old behaviour of returning the `Default::default()`
|
|
return 0;
|
|
};
|
|
|
|
// old behaviour would have also returned 0 here, but I'd argue if u64 can't fit in i64,
|
|
// it means we're over i64::MAX, thus that's what we should return
|
|
consumed
|
|
.try_into()
|
|
.inspect_err(|err| tracing::error!("Could not convert from u64 to i64: {err:?}"))
|
|
.unwrap_or(i64::MAX)
|
|
}
|
|
}
|