Skip to main content

agent_api/
api.rs

1use anyhow::Context;
2use anyhow::anyhow;
3use aya::maps::perf::PerfEventArrayBuffer;
4use chrono::Local;
5use cortexbrain_common::buffer_type::IpProtocols;
6use cortexbrain_common::buffer_type::PacketLossMetrics;
7use cortexbrain_common::buffer_type::PacketLog;
8use cortexbrain_common::buffer_type::TimeStampMetrics;
9use cortexbrain_common::formatters::{format_ipv4, format_ipv6};
10use cortexbrain_common::map_handlers::load_perf_event_array_from_mapdata;
11use std::str::FromStr;
12use std::sync::Mutex;
13use tonic::{Request, Response, Status};
14use tracing::info;
15
16use aya::maps::MapData;
17use std::result::Result::Ok;
18use tonic::async_trait;
19
20use aya::maps::HashMap as ayaHashMap;
21use std::collections::HashMap;
22use tokio::sync::mpsc;
23use tokio::task;
24
25use crate::agent::{
26    ConnectionEvent, DroppedPacketMetric, DroppedPacketsResponse, LatencyMetric,
27    LatencyMetricsResponse, VethEvent,
28};
29
30use cortexbrain_common::buffer_type::VethLog;
31
32// *  contains agent api configuration
33use crate::agent::{
34    ActiveConnectionResponse, AddIpToBlocklistRequest, BlocklistResponse, RequestActiveConnections,
35    RmIpFromBlocklistRequest, RmIpFromBlocklistResponse, VethHashMapResponse, VethResponse,
36    agent_server::Agent,
37};
38use crate::constants::PIN_BLOCKLIST_MAP_PATH;
39
40use crate::helpers::comm_to_string;
41use aya::maps::Map;
42use std::net::Ipv4Addr;
43use tracing::warn;
44
45use cortexbrain_common::buffer_type::BufferSize;
46use cortexbrain_common::buffer_type::fill_buffers;
47
48pub struct AgentApi {
49    //* event_rx is an istance of a mpsc receiver.
50    //* is used to receive the data from the transmitter (tx)
51    active_connection_event_rx: Mutex<mpsc::Receiver<Result<Vec<ConnectionEvent>, Status>>>,
52    pub(crate) active_connection_event_tx: mpsc::Sender<Result<Vec<ConnectionEvent>, Status>>,
53    latency_metrics_rx: Mutex<mpsc::Receiver<Result<Vec<LatencyMetric>, Status>>>,
54    pub(crate) latency_metrics_tx: mpsc::Sender<Result<Vec<LatencyMetric>, Status>>,
55    dropped_packet_metrics_rx: Mutex<mpsc::Receiver<Result<Vec<DroppedPacketMetric>, Status>>>,
56    pub(crate) dropped_packet_metrics_tx: mpsc::Sender<Result<Vec<DroppedPacketMetric>, Status>>,
57    tracked_veth_rx: Mutex<mpsc::Receiver<Result<Vec<VethEvent>, Status>>>,
58    pub(crate) tracked_veth_tx: mpsc::Sender<Result<Vec<VethEvent>, Status>>,
59}
60
61//initialize a default trait for AgentApi. Loads a name and a bpf istance.
62//this trait is essential for init the Agent.
63impl Default for AgentApi {
64    fn default() -> Self {
65        //
66        // init MapData from the kernel space
67        //
68
69        // TODO: in the future will be better to not use .unwrap()
70        let active_connection_events_array =
71            load_perf_event_array_from_mapdata("/sys/fs/bpf/maps/events_map").unwrap();
72        let network_metrics_events_array =
73            load_perf_event_array_from_mapdata("/sys/fs/bpf/trace_maps/net_metrics").unwrap();
74        let time_stamp_events_array =
75            load_perf_event_array_from_mapdata("/sys/fs/bpf/trace_maps/time_stamp_events").unwrap();
76        let tracked_veth_events_array =
77            load_perf_event_array_from_mapdata("/sys/fs/bpf/maps/veth_identity_map").unwrap();
78
79        //
80        // init a mpsc channels with TX (transmission) and RX(Receiver) components
81        //
82
83        let (conn_tx, conn_rx) = mpsc::channel(1024);
84        let (lat_tx, lat_rx) = mpsc::channel(2048);
85        let (drop_tx, drop_rx) = mpsc::channel(2048);
86        let (veth_tx, tracked_veth_rx) = mpsc::channel(1024);
87
88        // init the API to send the events from the agent to the CLI
89        let api = AgentApi {
90            active_connection_event_rx: conn_rx.into(),
91            active_connection_event_tx: conn_tx.clone(),
92            latency_metrics_rx: Mutex::new(lat_rx),
93            latency_metrics_tx: lat_tx.clone(),
94            dropped_packet_metrics_rx: Mutex::new(drop_rx),
95            dropped_packet_metrics_tx: drop_tx.clone(),
96            tracked_veth_rx: Mutex::new(tracked_veth_rx),
97            tracked_veth_tx: veth_tx.clone(),
98        };
99
100        // init map manager
101        //let map_manager = map_manager(maps)?
102
103        // init the buffers
104        let mut net_events_buffers = BufferSize::TcpEvents.set_buffer();
105        let mut net_metrics_buffers = BufferSize::NetworkMetricsEvents.set_buffer();
106        let mut ts_metrics_buffers = BufferSize::TimeMetricsEvents.set_buffer();
107        let mut veth_metrics_buffers = BufferSize::VethEvents.set_buffer();
108
109        // init the Vec of Buffers
110
111        let mut net_events_vec_buffer = Vec::<PerfEventArrayBuffer<MapData>>::new();
112        let mut net_metrics_vec_buffer = Vec::<PerfEventArrayBuffer<MapData>>::new();
113        let mut ts_events_vec_buffer = Vec::<PerfEventArrayBuffer<MapData>>::new();
114        let mut veth_events_vec_buffer = Vec::<PerfEventArrayBuffer<MapData>>::new();
115
116        // fill the Vec of Buffers
117
118        net_events_vec_buffer = fill_buffers(net_events_vec_buffer, active_connection_events_array);
119        net_metrics_vec_buffer = fill_buffers(net_metrics_vec_buffer, network_metrics_events_array);
120
121        ts_events_vec_buffer = fill_buffers(ts_events_vec_buffer, time_stamp_events_array);
122
123        veth_events_vec_buffer = fill_buffers(veth_events_vec_buffer, tracked_veth_events_array);
124
125        // For network metrics
126
127        //spawn an event readers
128        task::spawn(async move {
129            info!("Starting event listener");
130            //send the data through a mpsc channel
131            loop {
132                for buf in net_events_vec_buffer.iter_mut() {
133                    match buf.read_events(&mut net_events_buffers) {
134                        Ok(events) => {
135                            //read the events, this function is similar to the one used in identity/helpers.rs/display_events
136                            if events.read > 0 {
137                                for i in 0..events.read {
138                                    let data = &net_events_buffers[i];
139                                    if data.len() >= std::mem::size_of::<PacketLog>() {
140                                        let pl: PacketLog =
141                                            unsafe { std::ptr::read(data.as_ptr() as *const _) };
142                                        let src = Ipv4Addr::from(u32::from_be(pl.src_ip));
143                                        let dst = Ipv4Addr::from(u32::from_be(pl.dst_ip));
144                                        let src_port = u16::from_be(pl.src_port as u16);
145                                        let dst_port = u16::from_be(pl.dst_port as u16);
146                                        let event_id = pl.pid;
147
148                                        match IpProtocols::try_from(pl.proto) {
149                                            Ok(proto) => {
150                                                info!(
151                                                    "Event Id: {} Protocol: {:?} SRC: {}:{} -> DST: {}:{}",
152                                                    event_id, proto, src, src_port, dst, dst_port
153                                                );
154                                                info!("creating vector for the aggregated data");
155                                                let mut evt = Vec::new();
156                                                // insert event in the vector
157                                                info!("Inserting events into the vector");
158                                                //TODO: use a Arc<str> or Box<str> type instead of String type.
159                                                //The data doesn't need to implement any .copy() or .clone() trait
160                                                // using an Arc<str> type will also waste less resources
161                                                evt.push(ConnectionEvent {
162                                                    event_id: event_id.to_string(),
163                                                    src_ip_port: format!("{}:{}", src, src_port),
164                                                    dst_ip_port: format!("{}:{}", dst, dst_port),
165                                                });
166                                                info!("sending events to the MPSC channel");
167                                                let _ = conn_tx.send(Ok(evt)).await;
168                                            }
169                                            Err(_) => {
170                                                info!(
171                                                    "Event Id: {} Protocol: Unknown ({})",
172                                                    event_id, pl.proto
173                                                );
174                                            }
175                                        };
176                                    } else {
177                                        warn!(
178                                            "Received packet data too small: {} bytes",
179                                            data.len()
180                                        );
181                                    }
182                                }
183                            } else if events.lost > 0 {
184                                info!("[Agent/API] Lost {} events", events.lost);
185                            }
186                        }
187                        Err(e) => {
188                            eprintln!("Error while reading events: {}", e);
189                            tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
190                        }
191                    }
192                }
193                // small delay to avoid cpu congestion
194                tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
195            }
196        });
197
198        task::spawn(async move {
199            info!("Starting network metrics listener");
200
201            //send the data through a mpsc channel
202            loop {
203                for buf in net_metrics_vec_buffer.iter_mut() {
204                    match buf.read_events(&mut net_metrics_buffers) {
205                        Ok(events) => {
206                            //read the events, this function is similar to the one used in identity/helpers.rs/display_events
207                            if events.read > 0 {
208                                for i in 0..events.read {
209                                    let data = &net_metrics_buffers[i];
210                                    if data.len() >= std::mem::size_of::<PacketLossMetrics>() {
211                                        let nm: PacketLossMetrics =
212                                            unsafe { std::ptr::read(data.as_ptr() as *const _) };
213
214                                        let dropped_packet_metrics = DroppedPacketMetric {
215                                            tgid: nm.tgid,
216                                            process_name: comm_to_string(&nm.comm),
217                                            sk_drops: nm.sk_drops,
218                                            sk_err: nm.sk_err,
219                                            sk_err_soft: nm.sk_err_soft,
220                                            sk_backlog_len: nm.sk_backlog_len as u32,
221                                            sk_wmem_queued: nm.sk_write_memory_queued,
222                                            sk_rcvbuf: nm.sk_receive_buffer_size,
223                                            sk_ack_backlog: nm.sk_ack_backlog,
224                                            timestamp_us: nm.ts_us,
225                                        };
226
227                                        if dropped_packet_metrics.sk_drops > 0 {
228                                            let mut evt = Vec::new();
229                                            info!(
230                                                "Dropped Packet Metric - tgid: {}, process_name: {}, sk_drops: {}, sk_err: {}, sk_err_soft: {}, sk_backlog_len: {}, sk_wmem_queued: {}, sk_rcvbuf: {}, sk_ack_backlog: {}, timestamp_us: {}",
231                                                dropped_packet_metrics.tgid,
232                                                dropped_packet_metrics.process_name,
233                                                dropped_packet_metrics.sk_drops,
234                                                dropped_packet_metrics.sk_err,
235                                                dropped_packet_metrics.sk_err_soft,
236                                                dropped_packet_metrics.sk_backlog_len,
237                                                dropped_packet_metrics.sk_wmem_queued,
238                                                dropped_packet_metrics.sk_rcvbuf,
239                                                dropped_packet_metrics.sk_ack_backlog,
240                                                dropped_packet_metrics.timestamp_us
241                                            );
242                                            evt.push(dropped_packet_metrics.clone());
243                                            let _ = drop_tx.send(Ok(evt)).await;
244                                        }
245                                    } else {
246                                        warn!(
247                                            "Received network metrics data too small: {} bytes",
248                                            data.len()
249                                        );
250                                    }
251                                }
252                            }
253                        }
254                        Err(e) => {
255                            eprintln!("Errore nella lettura network metrics eventi: {}", e);
256                            tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
257                        }
258                    }
259                }
260                // small delay to avoid cpu congestion
261                tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
262            }
263        });
264
265        task::spawn(async move {
266            info!("Starting time stamp events listener");
267
268            //send the data through a mpsc channel
269            loop {
270                for buf in ts_events_vec_buffer.iter_mut() {
271                    match buf.read_events(&mut ts_metrics_buffers) {
272                        Ok(events) => {
273                            //read the events, this function is similar to the one used in identity/helpers.rs/display_events
274                            if events.read > 0 {
275                                for i in 0..events.read {
276                                    let data = &ts_metrics_buffers[i];
277                                    if data.len() >= std::mem::size_of::<TimeStampMetrics>() {
278                                        let tsm: TimeStampMetrics =
279                                            unsafe { std::ptr::read(data.as_ptr() as *const _) };
280                                        let saddr_v6 = tsm.saddr_v6;
281                                        let daddr_v6 = tsm.daddr_v6;
282                                        let latency_metric = LatencyMetric {
283                                            delta_us: tsm.delta_us,
284                                            timestamp_us: tsm.ts_us,
285                                            tgid: tsm.tgid,
286                                            process_name: comm_to_string(&tsm.comm),
287                                            local_port: tsm.lport as u32,
288                                            remote_port: tsm.dport_be as u32,
289                                            address_family: tsm.af as u32,
290                                            src_address_v4: format_ipv4(tsm.saddr_v4),
291                                            dst_address_v4: format_ipv4(tsm.daddr_v4),
292                                            src_address_v6: format_ipv6(&saddr_v6),
293                                            dst_address_v6: format_ipv6(&daddr_v6),
294                                        };
295                                        info!(
296                                            "Latency Metric - tgid: {}, process_name: {}, delta_us: {}, timestamp_us: {}, local_port: {}, remote_port: {}, address_family: {}, src_address_v4: {}, dst_address_v4: {}, src_address_v6: {}, dst_address_v6: {}",
297                                            latency_metric.tgid,
298                                            latency_metric.process_name,
299                                            latency_metric.delta_us,
300                                            latency_metric.timestamp_us,
301                                            latency_metric.local_port,
302                                            latency_metric.remote_port,
303                                            latency_metric.address_family,
304                                            latency_metric.src_address_v4,
305                                            latency_metric.dst_address_v4,
306                                            latency_metric.src_address_v6,
307                                            latency_metric.dst_address_v6
308                                        );
309                                        let mut evt = Vec::new();
310                                        evt.push(latency_metric.clone());
311                                        let _ = lat_tx.send(Ok(evt)).await;
312                                    } else {
313                                        warn!(
314                                            "Received time stamp metrics data too small: {} bytes",
315                                            data.len()
316                                        );
317                                    }
318                                }
319                            }
320                        }
321                        Err(e) => {
322                            eprintln!("Errore nella lettura time stamp eventi: {}", e);
323                            tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
324                        }
325                    }
326                }
327            }
328        });
329
330        task::spawn(async move {
331            info!("Starting time stamp events listener");
332
333            //send the data through a mpsc channel
334            loop {
335                for buf in veth_events_vec_buffer.iter_mut() {
336                    match buf.read_events(&mut veth_metrics_buffers) {
337                        Ok(events) => {
338                            //read the events, this function is similar to the one used in identity/helpers.rs/display_events
339                            if events.read > 0 {
340                                for i in 0..events.read {
341                                    info!("Found veth events {}", events.read);
342                                    let data = &veth_metrics_buffers[i];
343                                    if data.len() >= std::mem::size_of::<VethLog>() {
344                                        let veth: VethLog =
345                                            unsafe { std::ptr::read(data.as_ptr() as *const _) };
346                                        let veth_event = VethEvent {
347                                            name: String::from_utf8_lossy(unsafe {
348                                                std::slice::from_raw_parts(
349                                                    veth.name.as_ptr() as *const u8,
350                                                    veth.name.len() * std::mem::size_of::<u32>(),
351                                                )
352                                            })
353                                            .trim_end_matches('\0')
354                                            .to_string(),
355                                            state: veth.state,
356                                            dev_addr: String::from_utf8_lossy(unsafe {
357                                                std::slice::from_raw_parts(
358                                                    veth.dev_addr.as_ptr() as *const u8,
359                                                    veth.dev_addr.len()
360                                                        * std::mem::size_of::<u32>(),
361                                                )
362                                            })
363                                            .trim_end_matches('\0')
364                                            .to_string(),
365                                            event_type: veth.event_type.into(),
366                                            netns: veth.netns,
367                                            pid: veth.pid,
368                                        };
369                                        info!(
370                                            "Veth Event - name: {}, state: {}, dev_addr: {}, event_type: {}, netns: {}, pid: {}",
371                                            veth_event.name,
372                                            veth_event.state,
373                                            veth_event.dev_addr,
374                                            veth_event.event_type,
375                                            veth_event.netns,
376                                            veth_event.pid
377                                        );
378                                        let mut evt = Vec::new();
379                                        evt.push(veth_event.clone());
380                                        let _ = veth_tx.send(Ok(evt)).await;
381                                    } else {
382                                        warn!(
383                                            "Received time stamp metrics data too small: {} bytes",
384                                            data.len()
385                                        );
386                                    }
387                                }
388                            }
389                        }
390                        Err(e) => {
391                            eprintln!("Errore nella lettura time stamp eventi: {}", e);
392                            tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
393                        }
394                    }
395                }
396            }
397        });
398
399        api
400    }
401}
402
403//declare the blocklist hashmap structure
404//TODO: finish the creation of a blocklist hashmap
405#[async_trait]
406impl Agent for AgentApi {
407    // * read the incoming active_connections requests and returns a response with the
408    // * active connections. The data are transformed and sent to the api with a mpsc channel
409    async fn active_connections(
410        &self,
411        request: Request<RequestActiveConnections>,
412    ) -> Result<Response<ActiveConnectionResponse>, Status> {
413        //read request
414        let _req = request.into_inner();
415
416        //create the hashmap to process events from the mpsc channel queue
417        let mut aggregated_events: Vec<ConnectionEvent> = Vec::new();
418
419        //aggregate events
420        while let Ok(evt) = self.active_connection_event_rx.lock().unwrap().try_recv() {
421            if let Ok(vec) = evt {
422                aggregated_events.extend(vec);
423            }
424        }
425
426        //log response for debugging
427        info!(
428            "DEBUGGING RESPONSE FROM ACTIVE CONNECTION REQUEST: {:?}",
429            aggregated_events
430        );
431
432        //return response
433        Ok(Response::new(ActiveConnectionResponse {
434            status: "success".to_string(),
435            events: aggregated_events,
436        }))
437    }
438
439    // * creates and add ip to the blocklist
440    async fn add_ip_to_blocklist(
441        &self,
442        request: Request<AddIpToBlocklistRequest>,
443    ) -> Result<Response<BlocklistResponse>, Status> {
444        //read request
445        let req = request.into_inner();
446
447        //open blocklist map
448        let mapdata = MapData::from_pin("/sys/fs/bpf/maps/blocklist_map")
449            .expect("cannot open blocklist_map Mapdata");
450        let blocklist_mapdata = Map::HashMap(mapdata); //load mapdata
451        let mut blocklist_map: ayaHashMap<MapData, [u8; 4], [u8; 4]> =
452            ayaHashMap::try_from(blocklist_mapdata).unwrap();
453
454        if req.ip.is_none() {
455            // log blocklist event
456            info!("IP field in request is none");
457            info!("CURRENT BLOCKLIST: {:?}", blocklist_map);
458        } else {
459            // add ip to the blocklist
460            // log blocklist event
461            let _datetime = Local::now().to_string();
462            let ip = req.ip.unwrap();
463            //convert ip from string to [u8;4] type and insert into the bpf map
464            let u8_4_ip = Ipv4Addr::from_str(&ip).unwrap().octets();
465            //TODO: convert datetime in a kernel compatible format
466            blocklist_map
467                .insert(u8_4_ip, u8_4_ip, 0)
468                .map_err(|e| anyhow!("Cannot insert address in the blocklist. Reason: {}", e))
469                .unwrap();
470            info!("CURRENT BLOCKLIST: {:?}", blocklist_map);
471        }
472        let _path = std::env::var(PIN_BLOCKLIST_MAP_PATH)
473            .context("Blocklist map path not found!")
474            .unwrap();
475
476        //convert the maps with a buffer to match the protobuffer types
477        let mut converted_blocklist_map: HashMap<String, String> = HashMap::new();
478        for item in blocklist_map.iter() {
479            let (k, _v) = item.unwrap();
480            // convert keys and values from [u8;4] to String
481            let key = Ipv4Addr::from(k).to_string();
482            let value = Ipv4Addr::from(k).to_string();
483            converted_blocklist_map.insert(key, value);
484        }
485
486        //save ip into the blocklist
487        Ok(Response::new(BlocklistResponse {
488            status: "success".to_string(),
489            events: converted_blocklist_map,
490        }))
491    }
492
493    async fn check_blocklist(
494        &self,
495        _request: Request<()>,
496    ) -> Result<Response<BlocklistResponse>, Status> {
497        info!("Returning blocklist hashmap");
498        //open blocklist map
499        let mapdata = MapData::from_pin("/sys/fs/bpf/maps/blocklist_map")
500            .expect("cannot open blocklist_map Mapdata");
501        let blocklist_mapdata = Map::HashMap(mapdata); //load mapdata
502
503        let blocklist_map: ayaHashMap<MapData, [u8; 4], [u8; 4]> =
504            ayaHashMap::try_from(blocklist_mapdata).unwrap();
505
506        //convert the maps with a buffer to match the protobuffer types
507
508        let mut converted_blocklist_map: HashMap<String, String> = HashMap::new();
509        for item in blocklist_map.iter() {
510            let (k, _v) = item.unwrap();
511            // convert keys and values from [u8;4] to String
512            let key = Ipv4Addr::from(k).to_string();
513            let value = Ipv4Addr::from(k).to_string();
514            converted_blocklist_map.insert(key, value);
515        }
516        Ok(Response::new(BlocklistResponse {
517            status: "success".to_string(),
518            events: converted_blocklist_map,
519        }))
520    }
521    async fn rm_ip_from_blocklist(
522        &self,
523        request: Request<RmIpFromBlocklistRequest>,
524    ) -> Result<Response<RmIpFromBlocklistResponse>, Status> {
525        //read request
526        let req = request.into_inner();
527        info!("Removing ip from blocklist map");
528        //open blocklist map
529        let mapdata = MapData::from_pin("/sys/fs/bpf/maps/blocklist_map")
530            .expect("cannot open blocklist_map Mapdata");
531        let blocklist_mapdata = Map::HashMap(mapdata); //load mapdata
532        let mut blocklist_map: ayaHashMap<MapData, [u8; 4], [u8; 4]> =
533            ayaHashMap::try_from(blocklist_mapdata).unwrap();
534        //remove the address
535        let ip_to_remove = req.ip;
536        let u8_4_ip_to_remove = Ipv4Addr::from_str(&ip_to_remove).unwrap().octets();
537        let _ = blocklist_map.remove(&u8_4_ip_to_remove);
538
539        //convert the maps with a buffer to match the protobuffer types
540        let mut converted_blocklist_map: HashMap<String, String> = HashMap::new();
541        for item in blocklist_map.iter() {
542            let (k, v) = item.unwrap();
543            // convert keys and values from [u8;4] to String
544            let key = Ipv4Addr::from(k).to_string();
545            let value = Ipv4Addr::from(k).to_string();
546            converted_blocklist_map.insert(key, value);
547        }
548
549        Ok(Response::new(RmIpFromBlocklistResponse {
550            status: "Ip removed from blocklist".to_string(),
551            events: converted_blocklist_map,
552        }))
553    }
554
555    async fn get_latency_metrics(
556        &self,
557        request: Request<()>,
558    ) -> Result<Response<LatencyMetricsResponse>, Status> {
559        // Extract the request parameters
560        let _req = request.into_inner();
561        info!("Getting latency metrics");
562
563        // Here you would typically query your data source for the latency metrics
564        // For demonstration purposes, we'll return a dummy response
565
566        let mut aggregated_latency_metrics_events: Vec<LatencyMetric> = Vec::new();
567
568        while let Ok(evt) = self.latency_metrics_rx.lock().unwrap().try_recv() {
569            if let Ok(vec) = evt {
570                aggregated_latency_metrics_events.extend(vec);
571            }
572        }
573
574        let total_count = aggregated_latency_metrics_events.len() as u32;
575
576        let (average_latency_us, min_latency_us, max_latency_us) =
577            if !aggregated_latency_metrics_events.is_empty() {
578                let sum: u64 = aggregated_latency_metrics_events
579                    .iter()
580                    .map(|m| m.delta_us)
581                    .sum();
582                let avg = sum as f64 / aggregated_latency_metrics_events.len() as f64;
583
584                let min = aggregated_latency_metrics_events
585                    .iter()
586                    .map(|m| m.delta_us)
587                    .min()
588                    .unwrap_or(0) as f64;
589
590                let max = aggregated_latency_metrics_events
591                    .iter()
592                    .map(|m| m.delta_us)
593                    .max()
594                    .unwrap_or(0) as f64;
595
596                (avg, min, max)
597            } else {
598                (0.0, 0.0, 0.0)
599            };
600
601        info!(
602            "Latency metrics - total_count: {}, average: {:.2}us, min: {:.2}us, max: {:.2}us",
603            total_count, average_latency_us, min_latency_us, max_latency_us
604        );
605
606        let response = LatencyMetricsResponse {
607            status: "success".to_string(),
608            metrics: aggregated_latency_metrics_events,
609            total_count,
610            average_latency_us,
611            max_latency_us,
612            min_latency_us,
613        };
614
615        Ok(Response::new(response))
616    }
617
618    async fn get_dropped_packets_metrics(
619        &self,
620        request: Request<()>,
621    ) -> Result<Response<DroppedPacketsResponse>, Status> {
622        // Extract the request parameters
623        let _req = request.into_inner();
624        info!("Getting dropped packets metrics");
625
626        let mut aggregated_dropped_packet_metrics: Vec<DroppedPacketMetric> = Vec::new();
627        let mut total_drops = 0u32;
628
629        // Collect all metrics from channel
630        while let Ok(evt) = self.dropped_packet_metrics_rx.lock().unwrap().try_recv() {
631            if let Ok(vec) = evt {
632                for metric in vec {
633                    total_drops += metric.sk_drops as u32;
634                    aggregated_dropped_packet_metrics.push(metric);
635                }
636            }
637        }
638
639        info!(
640            "Dropped packets metrics - total_metrics: {}, total_drops: {}",
641            aggregated_dropped_packet_metrics.len(),
642            total_drops
643        );
644
645        let response = DroppedPacketsResponse {
646            status: "success".to_string(),
647            metrics: aggregated_dropped_packet_metrics,
648            total_drops,
649        };
650
651        Ok(Response::new(response))
652    }
653
654    async fn get_tracked_veth(
655        &self,
656        request: Request<()>,
657    ) -> Result<Response<VethResponse>, Status> {
658        let _req = request.into_inner();
659        info!("Getting tracked veth metrics");
660        let mut tracked_veth = Vec::<VethEvent>::new();
661        let mut tot_veth = 0 as i32;
662
663        while let Ok(evt) = self.tracked_veth_rx.lock().unwrap().try_recv() {
664            if let Ok(vec) = evt {
665                tracked_veth.extend(vec);
666            }
667        }
668        tot_veth = tracked_veth.len() as i32;
669
670        info!("Total tracked veth events: {}", tot_veth);
671        info!("Tracked veth: {:?}", &tracked_veth);
672
673        let veth_names: Vec<String> = tracked_veth.iter().map(|v| v.name.clone()).collect();
674
675        let response = VethResponse {
676            status: "success".to_string(),
677            veth_names,
678            tot_monitored_veth: tot_veth,
679        };
680
681        Ok(Response::new(response))
682    }
683
684    async fn get_tracked_veth_from_hash_map(
685        &self,
686        _request: Request<()>,
687    ) -> Result<Response<VethHashMapResponse>, Status> {
688        info!("Returning veth hashmap");
689        //open blocklist map
690        let mapdata = MapData::from_pin("/sys/fs/bpf/maps/tracked_veth")
691            .expect("cannot open tracked_veth Mapdata");
692        let tracked_veth_mapdata = Map::HashMap(mapdata); //load mapdata
693
694        let tracked_veth_map: ayaHashMap<MapData, [u8; 16], [u8; 8]> =
695            ayaHashMap::try_from(tracked_veth_mapdata).unwrap();
696
697        //convert the maps with a buffer to match the protobuffer types
698
699        let mut converted_tracked_veth_map: HashMap<String, String> = HashMap::new();
700        for item in tracked_veth_map.iter() {
701            let (k, v) = item.unwrap();
702            // convert keys and values from [u8;4] to String
703            let key = String::from_utf8(k.to_vec()).unwrap();
704            let value = String::from_utf8(v.to_vec()).unwrap();
705            converted_tracked_veth_map.insert(key, value);
706        }
707        Ok(Response::new(VethHashMapResponse {
708            status: "success".to_string(),
709            veths: converted_tracked_veth_map,
710        }))
711    }
712}