From 1d5d7b7f9804ef61fb9bb598c725eca16c16ae59 Mon Sep 17 00:00:00 2001 From: Dominik Csapak Date: Fri, 9 Aug 2024 10:20:32 +0200 Subject: [PATCH] fix #5622: backup client: properly handle rate/burst parameters The rate and burst parameters are integers, so the mapping from value with `.as_str()` will always return `None` effectively never applying any rate limit at all. Fix it by turning them into a HumanByte instead of an integer. To not crowd the parameter section so much, create a ClientRateLimitConfig struct that gets flattened into the parameter list of the backup client. To adapt the description of the parameters, add new schemas that copy the `HumanByte` schema but change the description. With this, the rate limit actually works, and there is no lower limit any more. The old TRAFFIC_CONTROL_RATE/BURST_SCHEMAs can be deleted since the client was the only user of them. Signed-off-by: Dominik Csapak --- pbs-api-types/src/traffic_control.rs | 51 ++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/pbs-api-types/src/traffic_control.rs b/pbs-api-types/src/traffic_control.rs index fb264531..0da327f2 100644 --- a/pbs-api-types/src/traffic_control.rs +++ b/pbs-api-types/src/traffic_control.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use proxmox_human_byte::HumanByte; -use proxmox_schema::{api, IntegerSchema, Schema, StringSchema, Updater}; +use proxmox_schema::{api, ApiType, Schema, StringSchema, Updater}; use crate::{ CIDR_SCHEMA, DAILY_DURATION_FORMAT, PROXMOX_SAFE_ID_FORMAT, SINGLE_LINE_COMMENT_SCHEMA, @@ -18,16 +18,6 @@ pub const TRAFFIC_CONTROL_ID_SCHEMA: Schema = StringSchema::new("Rule ID.") .max_length(32) .schema(); -pub const TRAFFIC_CONTROL_RATE_SCHEMA: Schema = - IntegerSchema::new("Rate limit (for Token bucket filter) in bytes/second.") - .minimum(100_000) - .schema(); - -pub const TRAFFIC_CONTROL_BURST_SCHEMA: Schema = - IntegerSchema::new("Size of the token bucket (for Token bucket filter) in bytes.") - .minimum(1000) - .schema(); - #[api( properties: { "rate-in": { @@ -71,6 +61,45 @@ impl RateLimitConfig { burst_out: burst, } } + + /// Create a [RateLimitConfig] from a [ClientRateLimitConfig] + pub fn from_client_config(limit: ClientRateLimitConfig) -> Self { + Self::with_same_inout(limit.rate, limit.burst) + } +} + +const CLIENT_RATE_LIMIT_SCHEMA: Schema = StringSchema { + description: "Rate limit (for Token bucket filter) in bytes/s with optional unit (B, KB (base 10), MB, GB, ..., KiB (base 2), MiB, Gib, ...).", + ..*HumanByte::API_SCHEMA.unwrap_string_schema() +} +.schema(); + +const CLIENT_BURST_SCHEMA: Schema = StringSchema { + description: "Size of the token bucket (for Token bucket filter) in bytes with optional unit (B, KB (base 10), MB, GB, ..., KiB (base 2), MiB, Gib, ...).", + ..*HumanByte::API_SCHEMA.unwrap_string_schema() +} +.schema(); + +#[api( + properties: { + rate: { + schema: CLIENT_RATE_LIMIT_SCHEMA, + optional: true, + }, + burst: { + schema: CLIENT_BURST_SCHEMA, + optional: true, + }, + }, +)] +#[derive(Serialize, Deserialize, Default, Clone)] +#[serde(rename_all = "kebab-case")] +/// Client Rate Limit Configuration +pub struct ClientRateLimitConfig { + #[serde(skip_serializing_if = "Option::is_none")] + rate: Option, + #[serde(skip_serializing_if = "Option::is_none")] + burst: Option, } #[api(