iota_types/
traffic_control.rs1use std::path::PathBuf;
6
7use serde::{Deserialize, Serialize};
8use serde_with::serde_as;
9
10pub const DEFAULT_SKETCH_CAPACITY: usize = 50_000;
15pub const DEFAULT_SKETCH_PROBABILITY: f64 = 0.999;
16pub const DEFAULT_SKETCH_TOLERANCE: f64 = 0.2;
17use rand::distributions::Distribution;
18
19const TRAFFIC_SINK_TIMEOUT_SEC: u64 = 300;
20
21#[derive(Clone, Debug, Deserialize, Serialize, Default)]
71#[serde(rename_all = "kebab-case")]
72pub enum ClientIdSource {
73 #[default]
74 SocketAddr,
75 XForwardedFor(usize),
76}
77
78#[derive(Clone, Debug, Deserialize, Serialize)]
79pub struct Weight(f32);
80
81impl Weight {
82 pub fn new(value: f32) -> Result<Self, &'static str> {
83 if (0.0..=1.0).contains(&value) {
84 Ok(Self(value))
85 } else {
86 Err("Weight must be between 0.0 and 1.0")
87 }
88 }
89
90 pub fn one() -> Self {
91 Self(1.0)
92 }
93
94 pub fn zero() -> Self {
95 Self(0.0)
96 }
97
98 pub fn value(&self) -> f32 {
99 self.0
100 }
101
102 pub fn is_sampled(&self) -> bool {
103 let mut rng = rand::thread_rng();
104 let sample = rand::distributions::Uniform::new(0.0, 1.0).sample(&mut rng);
105 sample <= self.value()
106 }
107}
108
109impl PartialEq for Weight {
110 fn eq(&self, other: &Self) -> bool {
111 self.value() == other.value()
112 }
113}
114
115#[serde_as]
116#[derive(Clone, Debug, Deserialize, Serialize)]
117#[serde(rename_all = "kebab-case")]
118pub struct RemoteFirewallConfig {
119 pub remote_fw_url: String,
120 pub destination_port: u16,
121 #[serde(default)]
122 pub delegate_spam_blocking: bool,
123 #[serde(default)]
124 pub delegate_error_blocking: bool,
125 #[serde(default = "default_drain_path")]
126 pub drain_path: PathBuf,
127 #[serde(default = "default_drain_timeout")]
130 pub drain_timeout_secs: u64,
131}
132
133fn default_drain_path() -> PathBuf {
134 PathBuf::from("/tmp/drain")
135}
136
137fn default_drain_timeout() -> u64 {
138 TRAFFIC_SINK_TIMEOUT_SEC
139}
140
141#[serde_as]
142#[derive(Clone, Debug, Deserialize, Serialize)]
143#[serde(rename_all = "kebab-case")]
144pub struct FreqThresholdConfig {
145 #[serde(default = "default_client_threshold")]
146 pub client_threshold: u64,
147 #[serde(default = "default_proxied_client_threshold")]
148 pub proxied_client_threshold: u64,
149 #[serde(default = "default_window_size_secs")]
150 pub window_size_secs: u64,
151 #[serde(default = "default_update_interval_secs")]
152 pub update_interval_secs: u64,
153 #[serde(default = "default_sketch_capacity")]
154 pub sketch_capacity: usize,
155 #[serde(default = "default_sketch_probability")]
156 pub sketch_probability: f64,
157 #[serde(default = "default_sketch_tolerance")]
158 pub sketch_tolerance: f64,
159}
160
161impl Default for FreqThresholdConfig {
162 fn default() -> Self {
163 Self {
164 client_threshold: default_client_threshold(),
165 proxied_client_threshold: default_proxied_client_threshold(),
166 window_size_secs: default_window_size_secs(),
167 update_interval_secs: default_update_interval_secs(),
168 sketch_capacity: default_sketch_capacity(),
169 sketch_probability: default_sketch_probability(),
170 sketch_tolerance: default_sketch_tolerance(),
171 }
172 }
173}
174
175fn default_client_threshold() -> u64 {
176 1_000_000
183}
184
185fn default_proxied_client_threshold() -> u64 {
186 10
187}
188
189fn default_window_size_secs() -> u64 {
190 30
191}
192
193fn default_update_interval_secs() -> u64 {
194 5
195}
196
197fn default_sketch_capacity() -> usize {
198 DEFAULT_SKETCH_CAPACITY
199}
200
201fn default_sketch_probability() -> f64 {
202 DEFAULT_SKETCH_PROBABILITY
203}
204
205fn default_sketch_tolerance() -> f64 {
206 DEFAULT_SKETCH_TOLERANCE
207}
208
209#[derive(Clone, Serialize, Deserialize, Debug, Default)]
212pub enum PolicyType {
213 #[default]
215 NoOp,
216
217 FreqThreshold(FreqThresholdConfig),
221
222 TestNConnIP(u64),
227 TestPanicOnInvocation,
231}
232
233#[serde_as]
234#[derive(Clone, Debug, Deserialize, Serialize)]
235#[serde(rename_all = "kebab-case")]
236pub struct PolicyConfig {
237 #[serde(default = "default_client_id_source")]
238 pub client_id_source: ClientIdSource,
239 #[serde(default = "default_connection_blocklist_ttl_sec")]
240 pub connection_blocklist_ttl_sec: u64,
241 #[serde(default)]
242 pub proxy_blocklist_ttl_sec: u64,
243 #[serde(default)]
244 pub spam_policy_type: PolicyType,
245 #[serde(default)]
246 pub error_policy_type: PolicyType,
247 #[serde(default = "default_channel_capacity")]
248 pub channel_capacity: usize,
249 #[serde(default = "default_spam_sample_rate")]
250 pub spam_sample_rate: Weight,
256 #[serde(default = "default_dry_run")]
257 pub dry_run: bool,
258}
259
260impl Default for PolicyConfig {
261 fn default() -> Self {
262 Self {
263 client_id_source: default_client_id_source(),
264 connection_blocklist_ttl_sec: 0,
265 proxy_blocklist_ttl_sec: 0,
266 spam_policy_type: PolicyType::NoOp,
267 error_policy_type: PolicyType::NoOp,
268 channel_capacity: 100,
269 spam_sample_rate: default_spam_sample_rate(),
270 dry_run: default_dry_run(),
271 }
272 }
273}
274
275pub fn default_client_id_source() -> ClientIdSource {
276 ClientIdSource::SocketAddr
277}
278
279pub fn default_connection_blocklist_ttl_sec() -> u64 {
280 60
281}
282pub fn default_channel_capacity() -> usize {
283 100
284}
285
286pub fn default_dry_run() -> bool {
287 true
288}
289
290pub fn default_spam_sample_rate() -> Weight {
291 Weight::new(0.2).unwrap()
292}