From 75ed2143cfa56aab7dde5059d7733f91aa4334cd Mon Sep 17 00:00:00 2001 From: Bastian Schmidt Date: Fri, 21 Jun 2024 10:33:22 +0200 Subject: [PATCH] Add [rntimatcher.gen] monitoring * Fix UL median basic filtering Python scripts/visualize_rnti_matching * Add kbps and plot-type arguments * Fix kbps calculation in Adapt traffic patterns * A-F: 128 B packets, 1ms-40ms interval * G: sinus * H-N: 256 B packets, 1ms-40ms interval Optimize [rntimatcher.gen] sending time window Implement adaptive sleeping between sending packets by subtracting the time it takes to send a packet from the delta time between packets are supposed to be sent --- scripts/visualize_rnti_matching.py | 28 +- src/logic/rnti_matcher.rs | 33 ++- src/logic/traffic_patterns.rs | 413 ++++++++++------------------- 3 files changed, 194 insertions(+), 280 deletions(-) diff --git a/scripts/visualize_rnti_matching.py b/scripts/visualize_rnti_matching.py index 88e16bf..24a9529 100755 --- a/scripts/visualize_rnti_matching.py +++ b/scripts/visualize_rnti_matching.py @@ -21,13 +21,14 @@ DEFAULT_RESET_TIMESTAMPS = True DEFAULT_FILTER_KEEP_REST = False DEFAULT_EXPORT_PATH = './.export/' +DEFAULT_DIASHOW_KBPS = False # RNTI Filterting DCI_THRESHOLD = 0 EMPTY_DCI_RATIO_THRESHOLD = 0.99 SAMPLES_THRESHOLD = 5 -MAX_TOTAL_UL_FACTOR = 100.0 +MAX_TOTAL_UL_FACTOR = 200.0 MIN_TOTAL_UL_FACTOR = 0.005 # x% of the expected UL traffic MAX_UL_PER_DCI_THRESHOLD = 5_000_000 MIN_OCCURENCES_FACTOR = 0.005 @@ -397,8 +398,12 @@ def __init__(self, ax, data: list, settings): def plot(self): self.ax.clear() - df_kbps = self.data[self.index].filtered_df.resample('1s').median().mul(8 / 1_000) - plot_df(plot_pandas_line, df_kbps, axes=self.ax) + df = self.data[self.index].filtered_df + print_info(f"Highest DCI count RNTI: {df.count().idxmax()}") + if self.settings.kbps: + df = df.resample('1s').sum().mul(8).div(1000) + + plot_df(DEFAULT_DIASHOW_PLOT_TYPE_CHOICES[self.settings.plot_type], df, axes=self.ax) def check_data(self, file_index) -> bool: if isinstance(self.data[file_index], FilteredRecording): @@ -550,7 +555,7 @@ def export(settings): filtered_data = filter_dataset(settings, raw_recording) df = move_column_to_front(filtered_data.filtered_df, '11985') - df_kbps = df.resample('1s').median().mul(8 / 1_000) + df_kbps = df.resample('1s').sum().mul(8).div(1000) # Replace the first directory and change the file extension os.makedirs(os.path.dirname(export_base_path), exist_ok=True) @@ -674,6 +679,12 @@ def plot_pandas_hist(ax, df): ax.set_ylabel('Frequency') # ax.set_title('Histogram of UL Bytes') +DEFAULT_DIASHOW_PLOT_TYPE = 'scatter' +DEFAULT_DIASHOW_PLOT_TYPE_CHOICES = { + 'scatter': plot_pandas_scatter, + 'line': plot_pandas_line, + 'hist': plot_pandas_hist, +} def plot_basic_filtered(settings, recording): @@ -758,6 +769,15 @@ def plot_basic_filtered(settings, recording): type=bool, default=DEFAULT_PLOT_FILTERED, help='Display filtered RNTIs in the plot (default: {DEFAULT_PLOT_FILTERED})') + parser_diashow.add_argument('--kbps', + type=bool, + default=DEFAULT_DIASHOW_KBPS, + help='Resample to kbps (default: {DEFAULT_DIASHOW_KBPS})') + parser_diashow.add_argument('--plot-type', + type=str, + choices=list(DEFAULT_DIASHOW_PLOT_TYPE_CHOICES.keys()), + default=DEFAULT_DIASHOW_PLOT_TYPE, + help='The type of the plot (default: {DEFAULT_DIASHOW_PLOT_TYPE})') # standardize subcommand parser_standardize = subparsers.add_parser('standardize', help='Run standardize mode') diff --git a/src/logic/rnti_matcher.rs b/src/logic/rnti_matcher.rs index a89ab5e..91f8851 100644 --- a/src/logic/rnti_matcher.rs +++ b/src/logic/rnti_matcher.rs @@ -38,7 +38,7 @@ pub const MATCHING_UL_BYTES_UPPER_BOUND_FACTOR: f64 = 4.0; pub const TIME_MS_TO_US_FACTOR: u64 = 1000; pub const COLLECT_DCI_MAX_TIMESTAMP_DELTA_US: u64 = 50000; -pub const BASIC_FILTER_MAX_TOTAL_UL_FACTOR: f64 = 100.0; +pub const BASIC_FILTER_MAX_TOTAL_UL_FACTOR: f64 = 200.0; pub const BASIC_FILTER_MIN_TOTAL_UL_FACTOR: f64 = 0.005; pub const BASIC_FILTER_MAX_UL_PER_DCI: u64 = 5_000_000; pub const BASIC_FILTER_MIN_OCCURENCES_FACTOR: f64 = 0.005; @@ -405,6 +405,8 @@ fn run_traffic_generator( determine_process_id() )); + let mut last_timemstamp_us: Option = None; + loop { match check_rx_state(&rx_local_gen_state) { Ok(Some(new_state)) => gen_state = new_state, @@ -424,7 +426,7 @@ fn run_traffic_generator( break; } LocalGeneratorState::SendPattern(ref destination, ref mut pattern) => { - match gen_handle_send_pattern(&socket, destination, pattern) { + match gen_handle_send_pattern(&socket, destination, pattern, &mut last_timemstamp_us) { Ok(Some(_)) => { /* stay in the state and keep sending */ }, Ok(None) => gen_state = LocalGeneratorState::PatternSent, Err(e) => { @@ -435,6 +437,7 @@ fn run_traffic_generator( } LocalGeneratorState::PatternSent => { print_info("[rntimatcher.gen] Finished sending pattern!"); + last_timemstamp_us = None; gen_state = LocalGeneratorState::Idle } } @@ -468,11 +471,33 @@ fn gen_handle_send_pattern( socket: &UdpSocket, destination: &str, pattern: &mut TrafficPattern, + last_sent_timemstamp_us: &mut Option, ) -> Result> { match pattern.messages.pop_front() { Some(msg) => { - thread::sleep(Duration::from_millis(msg.time_ms as u64)); + let sleep_us: u64; + + let now_us = chrono::Utc::now().timestamp_micros() as u64; + if let Some(ref mut timestamp_us) = last_sent_timemstamp_us { + /* Determine time delta and adapt sleeping time */ + let delta = now_us - *timestamp_us; + if delta > msg.time_ms as u64 * TIME_MS_TO_US_FACTOR { + print_info(&format!("[rntimatcher.gen] sending time interval exceeded by: {:?}us", delta)); + sleep_us = msg.time_ms as u64 * TIME_MS_TO_US_FACTOR; + } else { + sleep_us = (msg.time_ms as u64 * TIME_MS_TO_US_FACTOR) - delta; + } + } else { + /* First packet, just sleep and send */ + sleep_us = msg.time_ms as u64 * TIME_MS_TO_US_FACTOR; + } + + thread::sleep(Duration::from_micros(sleep_us)); + + *last_sent_timemstamp_us = Some(chrono::Utc::now().timestamp_micros() as u64); + socket.send_to(&msg.payload, destination)?; + Ok(Some(())) } None => Ok(None) @@ -603,7 +628,7 @@ impl TrafficCollection { /* ZERO MEDIAN */ .filter(|(_, ue_traffic)| { match ue_traffic.feature_ul_bytes_median_mean_variance() { - Ok((median, _, _)) if median <= 0.0 => true, + Ok((median, _, _)) if median > 0.0 => true, _ => { stats.zero_ul_median += 1; false diff --git a/src/logic/traffic_patterns.rs b/src/logic/traffic_patterns.rs index 1260f88..2cd14cd 100644 --- a/src/logic/traffic_patterns.rs +++ b/src/logic/traffic_patterns.rs @@ -11,20 +11,20 @@ use crate::math_util::{calculate_mean_variance, calculate_median, standardize_fe )] pub enum RntiMatchingTrafficPatternType { #[default] - A, /* t: 24 sec, 1KB packets, 1ms interval => ? Mbit/s */ - B, /* t: 24 sec, 2KB packets, 5ms interval => ? Mbit/s */ - C, /* t: 24 sec, 4KB packets, 5ms interval => ? Mbit/s */ - D, /* t: 24 sec, 8KB packets, 5ms interval => ~ 5.8 Mbit/s */ - E, /* t: 24 sec, 16KB packets, 10ms interval => ? Mbit/s */ - F, /* t: 24 sec, 32KB packets, 10ms interval => ? Mbit/s */ - G, - H, - I, - J, - K, - L, - M, - N, + A, /* t: 10 sec, 128B packets, 1ms interval => ? Mbit/s */ + B, /* t: 10 sec, 128B packets, 5ms interval => ? Mbit/s */ + C, /* t: 10 sec, 128B packets, 10ms interval => ? Mbit/s */ + D, /* t: 10 sec, 128B packets, 15ms interval => ~ 5.8 Mbit/s */ + E, /* t: 10 sec, 128B packets, 20ms interval => ? Mbit/s */ + F, /* t: 10 sec, 128B packets, 40ms interval => ? Mbit/s */ + G, /* sinus 128B packets, 5ms interval => ? Mbit/s */ + H, /* t: 10 sec, 256B packets, 1ms interval => ? Mbit/s */ + I, /* t: 10 sec, 256B packets, 5ms interval => ? Mbit/s */ + J, /* t: 10 sec, 256B packets, 10ms interval => ? Mbit/s */ + K, /* t: 10 sec, 256B packets, 15ms interval => ~ 5.8 Mbit/s */ + L, /* t: 10 sec, 256B packets, 20ms interval => ? Mbit/s */ + M, /* t: 10 sec, 256B packets, 40ms interval => ? Mbit/s */ + N, /* t: 10 sec, 256B packets, 40ms interval | 5 sec send, 5 sec nothing */ O, P, /* 5s "small" + 5s "big" */ Q, /* test "no" traffic */ @@ -189,7 +189,7 @@ fn generate_incremental_pattern( }; messages.push_back(TrafficPatternMessage { time_ms: interval_ms, - payload: vec![0xA0; 500 + increment], + payload: vec![0xA0; increment], }) } messages.push_back(TrafficPatternMessage { @@ -208,7 +208,8 @@ fn generate_incremental_pattern( fn pattern_a() -> TrafficPattern { TrafficPattern { pattern_type: RntiMatchingTrafficPatternType::A, - messages: generate_incremental_pattern(1, 10, 20000, 4000), + messages: generate_incremental_pattern(1, 7, 10000, 1), + /* DUMMY STD_VEC */ std_vec: vec![ (4298.972, 655.833), (8977880.222, 1309843.824), @@ -225,7 +226,8 @@ fn pattern_a() -> TrafficPattern { fn pattern_b() -> TrafficPattern { TrafficPattern { pattern_type: RntiMatchingTrafficPatternType::B, - messages: generate_incremental_pattern(5, 11, 20000, 4000), + messages: generate_incremental_pattern(5, 7, 10000, 1), + /* DUMMY STD_VEC */ std_vec: vec![ (5112.829, 687.871), (35530994.057, 5229654.427), @@ -242,7 +244,8 @@ fn pattern_b() -> TrafficPattern { fn pattern_c() -> TrafficPattern { TrafficPattern { pattern_type: RntiMatchingTrafficPatternType::C, - messages: generate_incremental_pattern(5, 12, 20000, 4000), + messages: generate_incremental_pattern(10, 7, 10000, 1), + /* DUMMY STD_VEC */ std_vec: vec![ (5506.000, 370.136), (46840983.314, 3698612.070), @@ -259,7 +262,8 @@ fn pattern_c() -> TrafficPattern { fn pattern_d() -> TrafficPattern { TrafficPattern { pattern_type: RntiMatchingTrafficPatternType::D, - messages: generate_incremental_pattern(5, 13, 20000, 4000), + messages: generate_incremental_pattern(15, 7, 10000, 1), + /* DUMMY STD_VEC */ std_vec: vec![ (4033.685, 1241.680), (40102402.815, 12125065.759), @@ -276,7 +280,8 @@ fn pattern_d() -> TrafficPattern { fn pattern_e() -> TrafficPattern { TrafficPattern { pattern_type: RntiMatchingTrafficPatternType::E, - messages: generate_incremental_pattern(10, 14, 20000, 4000), + messages: generate_incremental_pattern(20, 7, 10000, 1), + /* DUMMY STD_VEC */ std_vec: vec![ (7076.078, 1322.567), (84959693.091, 16536550.367), @@ -293,7 +298,8 @@ fn pattern_e() -> TrafficPattern { fn pattern_f() -> TrafficPattern { TrafficPattern { pattern_type: RntiMatchingTrafficPatternType::F, - messages: generate_incremental_pattern(10, 15, 20000, 4000), + messages: generate_incremental_pattern(40, 7, 10000, 1), + /* DUMMY STD_VEC */ std_vec: vec![ (4963.692, 1691.421), (60475162.154, 18629696.408), @@ -308,301 +314,164 @@ fn pattern_f() -> TrafficPattern { } fn pattern_g() -> TrafficPattern { + let mut messages: VecDeque = VecDeque::::new(); + + let amplitude = 128.0; + let vertical_shift = 256.0; + let angular_frequency = 1.5 * std::f64::consts::PI; // omega = pi for T = 3s + let sending_interval_ms = 5; + let pattern_interval_ms = 10000; + + for i in 0..(pattern_interval_ms / sending_interval_ms as u32) { + let t = i as f64 * sending_interval_ms as f64 / 1000.0; + let packet_size = + (amplitude * (angular_frequency * t).sin() + vertical_shift).round() as usize; + messages.push_back(TrafficPatternMessage { + time_ms: sending_interval_ms, + payload: vec![0xA0; packet_size], + }); + } + TrafficPattern { pattern_type: RntiMatchingTrafficPatternType::G, - messages: VecDeque::from_iter([ - /* to be determined */ - TrafficPatternMessage { - time_ms: 10, - payload: vec![0xA0; 8192], - }, - TrafficPatternMessage { - time_ms: 10, - payload: vec![0xA1; 8192], - }, - TrafficPatternMessage { - time_ms: 10, - payload: vec![0xA2; 8192], - }, - TrafficPatternMessage { - time_ms: 10, - payload: vec![0xA3; 8192], - }, - TrafficPatternMessage { - time_ms: 10, - payload: vec![0xA4; 8192], - }, - TrafficPatternMessage { - time_ms: 500, - payload: vec![0xA4; 8192], - }, - TrafficPatternMessage { - time_ms: 10, - payload: vec![0xA1; 8192], - }, - TrafficPatternMessage { - time_ms: 10, - payload: vec![0xA2; 8192], - }, - TrafficPatternMessage { - time_ms: 10, - payload: vec![0xA3; 8192], - }, - TrafficPatternMessage { - time_ms: 10, - payload: vec![0xA4; 8192], - }, - TrafficPatternMessage { - time_ms: 500, - payload: vec![0xA4; 512], - }, - ]), - ..Default::default() + messages, + /* DUMMY STD_VEC */ + std_vec: vec![ + (4963.692, 1691.421), + (60475162.154, 18629696.408), + (13202.769, 1750.840), + (12332.931, 881.872), + (64867114.805, 20203503.942), + (2344.231, 301.511), + (5792.186, 2363.042), + (1210676863.405, 1269774046.111), + ], } } fn pattern_h() -> TrafficPattern { - let mut messages: VecDeque = VecDeque::::new(); - /* to be determined */ - for _ in 0..1000 { - messages.push_back(TrafficPatternMessage { - time_ms: 10, - payload: vec![0xA0; 512], - }) - } TrafficPattern { pattern_type: RntiMatchingTrafficPatternType::H, - messages, - ..Default::default() + messages: generate_incremental_pattern(1, 8, 10000, 1), + /* DUMMY STD_VEC */ + std_vec: vec![ + (4298.972, 655.833), + (8977880.222, 1309843.824), + (914.222, 100.852), + (2098.996, 192.174), + (14021412.605, 1704132.447), + (4694.583, 654.029), + (6267.872, 969.600), + (294670529.455, 312539196.447), + ], } } fn pattern_i() -> TrafficPattern { - let mut messages: VecDeque = VecDeque::::new(); - - let amplitude = 5000.0; - let vertical_shift = 10000.0; - let angular_frequency = std::f64::consts::PI; // omega = pi for T = 2s - let time_interval_ms = 50; // Constant inter-arrival time in milliseconds - - for i in 0..200 { - let t = i as f64 * time_interval_ms as f64 / 1000.0; - let packet_size = - (amplitude * (angular_frequency * t).sin() + vertical_shift).round() as usize; - messages.push_back(TrafficPatternMessage { - time_ms: time_interval_ms, - payload: vec![0xA0; packet_size], - }); - } - TrafficPattern { pattern_type: RntiMatchingTrafficPatternType::I, - messages, - ..Default::default() + messages: generate_incremental_pattern(5, 8, 10000, 1), + /* DUMMY STD_VEC */ + std_vec: vec![ + (4298.972, 655.833), + (8977880.222, 1309843.824), + (914.222, 100.852), + (2098.996, 192.174), + (14021412.605, 1704132.447), + (4694.583, 654.029), + (6267.872, 969.600), + (294670529.455, 312539196.447), + ], } } fn pattern_j() -> TrafficPattern { - let mut messages: VecDeque = VecDeque::::new(); - /* to be determined */ - for _ in 0..500 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 32], - }) - } - for _ in 0..500 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 64], - }) - } - for _ in 0..500 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 32], - }) - } - for _ in 0..500 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 64], - }) - } TrafficPattern { pattern_type: RntiMatchingTrafficPatternType::J, - messages, - ..Default::default() + messages: generate_incremental_pattern(10, 8, 10000, 1), + /* DUMMY STD_VEC */ + std_vec: vec![ + (4298.972, 655.833), + (8977880.222, 1309843.824), + (914.222, 100.852), + (2098.996, 192.174), + (14021412.605, 1704132.447), + (4694.583, 654.029), + (6267.872, 969.600), + (294670529.455, 312539196.447), + ], } } -/* K and J do not show a pattern similar to J -> maybe, 250ms is too short */ fn pattern_k() -> TrafficPattern { - let mut messages: VecDeque = VecDeque::::new(); - /* to be determined */ - for _ in 0..250 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 32], - }) - } - for _ in 0..250 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 64], - }) - } - for _ in 0..250 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 32], - }) - } - for _ in 0..250 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 64], - }) - } TrafficPattern { pattern_type: RntiMatchingTrafficPatternType::K, - messages, - ..Default::default() + messages: generate_incremental_pattern(15, 8, 10000, 1), + /* DUMMY STD_VEC */ + std_vec: vec![ + (4298.972, 655.833), + (8977880.222, 1309843.824), + (914.222, 100.852), + (2098.996, 192.174), + (14021412.605, 1704132.447), + (4694.583, 654.029), + (6267.872, 969.600), + (294670529.455, 312539196.447), + ], } } fn pattern_l() -> TrafficPattern { - let mut messages: VecDeque = VecDeque::::new(); - /* to be determined */ - for _ in 0..250 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 32], - }) - } - - messages.push_back(TrafficPatternMessage { - time_ms: 250, - payload: vec![0xA0; 32], - }); - - for _ in 0..250 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 32], - }) - } - - messages.push_back(TrafficPatternMessage { - time_ms: 250, - payload: vec![0xA0; 32], - }); - TrafficPattern { pattern_type: RntiMatchingTrafficPatternType::L, - messages, - ..Default::default() + messages: generate_incremental_pattern(20, 8, 10000, 1), + /* DUMMY STD_VEC */ + std_vec: vec![ + (4298.972, 655.833), + (8977880.222, 1309843.824), + (914.222, 100.852), + (2098.996, 192.174), + (14021412.605, 1704132.447), + (4694.583, 654.029), + (6267.872, 969.600), + (294670529.455, 312539196.447), + ], } } fn pattern_m() -> TrafficPattern { - let mut messages: VecDeque = VecDeque::::new(); - /* to be determined */ - for _ in 0..500 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 32], - }) - } - for _ in 0..500 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 64], - }) - } - for _ in 0..500 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 32], - }) - } - for _ in 0..500 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 64], - }) - } - - messages.push_back(TrafficPatternMessage { - time_ms: 250, - payload: vec![0xA0; 16000], - }); - - for _ in 0..500 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 32], - }) - } - for _ in 0..500 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 64], - }) - } - - messages.push_back(TrafficPatternMessage { - time_ms: 250, - payload: vec![0xA0; 16000], - }); - - for _ in 0..500 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 32], - }) - } - for _ in 0..500 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 64], - }) - } - TrafficPattern { pattern_type: RntiMatchingTrafficPatternType::M, - messages, - ..Default::default() + messages: generate_incremental_pattern(40, 8, 10000, 1), + /* DUMMY STD_VEC */ + std_vec: vec![ + (4298.972, 655.833), + (8977880.222, 1309843.824), + (914.222, 100.852), + (2098.996, 192.174), + (14021412.605, 1704132.447), + (4694.583, 654.029), + (6267.872, 969.600), + (294670529.455, 312539196.447), + ], } } fn pattern_n() -> TrafficPattern { - let mut messages: VecDeque = VecDeque::::new(); - /* to be determined */ - for _ in 0..500 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 32], - }) - } - for _ in 0..500 { - messages.push_back(TrafficPatternMessage { - time_ms: 1, - payload: vec![0xA0; 64], - }) - } - - for _ in 0..50 { - messages.push_back(TrafficPatternMessage { - time_ms: 20, - payload: vec![0xA0; 512], - }) - } - TrafficPattern { pattern_type: RntiMatchingTrafficPatternType::N, - messages, - ..Default::default() + messages: generate_incremental_pattern(40, 8, 5000, 5000), + /* DUMMY STD_VEC */ + std_vec: vec![ + (4298.972, 655.833), + (8977880.222, 1309843.824), + (914.222, 100.852), + (2098.996, 192.174), + (14021412.605, 1704132.447), + (4694.583, 654.029), + (6267.872, 969.600), + (294670529.455, 312539196.447), + ], } }