diff --git a/pbs-api-types/src/traffic_control.rs b/pbs-api-types/src/traffic_control.rs index 210f53ac..a1fcb7b5 100644 --- a/pbs-api-types/src/traffic_control.rs +++ b/pbs-api-types/src/traffic_control.rs @@ -30,13 +30,6 @@ pub const TRAFFIC_CONTROL_BURST_SCHEMA: Schema = IntegerSchema::new( #[api( properties: { - name: { - schema: TRAFFIC_CONTROL_ID_SCHEMA, - }, - comment: { - optional: true, - schema: SINGLE_LINE_COMMENT_SCHEMA, - }, "rate-in": { type: HumanByte, optional: true, @@ -53,6 +46,45 @@ pub const TRAFFIC_CONTROL_BURST_SCHEMA: Schema = IntegerSchema::new( type: HumanByte, optional: true, }, + }, +)] +#[derive(Serialize,Deserialize,Default,Clone,Updater)] +#[serde(rename_all = "kebab-case")] +/// Rate Limit Configuration +pub struct RateLimitConfig { + #[serde(skip_serializing_if="Option::is_none")] + pub rate_in: Option, + #[serde(skip_serializing_if="Option::is_none")] + pub burst_in: Option, + #[serde(skip_serializing_if="Option::is_none")] + pub rate_out: Option, + #[serde(skip_serializing_if="Option::is_none")] + pub burst_out: Option, +} + +impl RateLimitConfig { + pub fn with_same_inout(rate: Option, burst: Option) -> Self { + Self { + rate_in: rate, + burst_in: burst, + rate_out: rate, + burst_out: burst, + } + } +} + +#[api( + properties: { + name: { + schema: TRAFFIC_CONTROL_ID_SCHEMA, + }, + comment: { + optional: true, + schema: SINGLE_LINE_COMMENT_SCHEMA, + }, + limit: { + type: RateLimitConfig, + }, network: { type: Array, items: { @@ -78,14 +110,8 @@ pub struct TrafficControlRule { pub comment: Option, /// Rule applies to Source IPs within this networks pub network: Vec, - #[serde(skip_serializing_if="Option::is_none")] - pub rate_in: Option, - #[serde(skip_serializing_if="Option::is_none")] - pub burst_in: Option, - #[serde(skip_serializing_if="Option::is_none")] - pub rate_out: Option, - #[serde(skip_serializing_if="Option::is_none")] - pub burst_out: Option, + #[serde(flatten)] + pub limit: RateLimitConfig, // fixme: expose this? // /// Bandwidth is shared accross all connections // #[serde(skip_serializing_if="Option::is_none")]