mirror of
https://github.com/DaLaw2/NetGuardia.git
synced 2026-08-24 14:10:28 +09:00
Add egress full statistics support
This commit is contained in:
parent
ac829024f6
commit
7b8801a146
@ -7,31 +7,53 @@ use net_guardia_common::model::ip_address::{EbpfAddrPortV4, EbpfAddrPortV6};
|
||||
use net_guardia_common::MAX_STATS;
|
||||
|
||||
#[map]
|
||||
static IPV4_DST_1MIN: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
static IPV4_EGRESS_SRC_1MIN: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV4_DST_10MIN: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
static IPV4_EGRESS_SRC_10MIN: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV4_DST_1HOUR: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
static IPV4_EGRESS_SRC_1HOUR: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV6_DST_1MIN: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
static IPV6_EGRESS_SRC_1MIN: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV6_DST_10MIN: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
static IPV6_EGRESS_SRC_10MIN: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV6_DST_1HOUR: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
static IPV6_EGRESS_SRC_1HOUR: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV4_EGRESS_DST_1MIN: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV4_EGRESS_DST_10MIN: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV4_EGRESS_DST_1HOUR: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV6_EGRESS_DST_1MIN: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV6_EGRESS_DST_10MIN: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV6_EGRESS_DST_1HOUR: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
|
||||
pub fn ipv4_update_stats(event: &IPv4Event) {
|
||||
unsafe {
|
||||
let now = bpf_ktime_get_ns();
|
||||
let source = [event.source_ip, event.source_port as u32];
|
||||
ipv4_update_flow_stats(&IPV4_DST_1MIN, &source, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_DST_10MIN, &source, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_DST_1HOUR, &source, event, now);
|
||||
let destination = [event.destination_ip, event.destination_port as u32];
|
||||
ipv4_update_flow_stats(&IPV4_EGRESS_SRC_1MIN, &source, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_EGRESS_SRC_10MIN, &source, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_EGRESS_SRC_1HOUR, &source, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_EGRESS_DST_1MIN, &destination, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_EGRESS_DST_10MIN, &destination, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_EGRESS_DST_1HOUR, &destination, event, now);
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,9 +61,13 @@ pub fn ipv6_update_stats(event: &IPv6Event) {
|
||||
unsafe {
|
||||
let now = bpf_ktime_get_ns();
|
||||
let source = [event.source_ip, event.source_port as u128];
|
||||
ipv6_update_flow_status(&IPV6_DST_1MIN, &source, event, now);
|
||||
ipv6_update_flow_status(&IPV6_DST_10MIN, &source, event, now);
|
||||
ipv6_update_flow_status(&IPV6_DST_1HOUR, &source, event, now);
|
||||
let destination = [event.destination_ip, event.destination_port as u128];
|
||||
ipv6_update_flow_status(&IPV6_EGRESS_SRC_1MIN, &source, event, now);
|
||||
ipv6_update_flow_status(&IPV6_EGRESS_SRC_10MIN, &source, event, now);
|
||||
ipv6_update_flow_status(&IPV6_EGRESS_SRC_1HOUR, &source, event, now);
|
||||
ipv6_update_flow_status(&IPV6_EGRESS_DST_1MIN, &destination, event, now);
|
||||
ipv6_update_flow_status(&IPV6_EGRESS_DST_10MIN, &destination, event, now);
|
||||
ipv6_update_flow_status(&IPV6_EGRESS_DST_1HOUR, &destination, event, now);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,40 +7,40 @@ use net_guardia_common::model::ip_address::{EbpfAddrPortV4, EbpfAddrPortV6};
|
||||
use net_guardia_common::MAX_STATS;
|
||||
|
||||
#[map]
|
||||
static IPV4_SRC_1MIN: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
static IPV4_INGRESS_SRC_1MIN: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV4_SRC_10MIN: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
static IPV4_INGRESS_SRC_10MIN: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV4_SRC_1HOUR: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
static IPV4_INGRESS_SRC_1HOUR: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV6_SRC_1MIN: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
static IPV6_INGRESS_SRC_1MIN: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV6_SRC_10MIN: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
static IPV6_INGRESS_SRC_10MIN: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV6_SRC_1HOUR: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
static IPV6_INGRESS_SRC_1HOUR: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV4_DST_1MIN: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
static IPV4_INGRESS_DST_1MIN: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV4_DST_10MIN: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
static IPV4_INGRESS_DST_10MIN: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV4_DST_1HOUR: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
static IPV4_INGRESS_DST_1HOUR: LruHashMap<EbpfAddrPortV4, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV6_DST_1MIN: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
static IPV6_INGRESS_DST_1MIN: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV6_DST_10MIN: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
static IPV6_INGRESS_DST_10MIN: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
#[map]
|
||||
static IPV6_DST_1HOUR: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
static IPV6_INGRESS_DST_1HOUR: LruHashMap<EbpfAddrPortV6, EbpfFlowStats> =
|
||||
LruHashMap::with_max_entries(MAX_STATS, 0);
|
||||
|
||||
pub fn ipv4_update_stats(event: &IPv4Event) {
|
||||
@ -48,12 +48,12 @@ pub fn ipv4_update_stats(event: &IPv4Event) {
|
||||
let now = bpf_ktime_get_ns();
|
||||
let source = [event.source_ip, event.source_port as u32];
|
||||
let destination = [event.destination_ip, event.destination_port as u32];
|
||||
ipv4_update_flow_stats(&IPV4_SRC_1MIN, &source, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_SRC_10MIN, &source, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_SRC_1HOUR, &source, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_DST_1MIN, &destination, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_DST_10MIN, &destination, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_DST_1HOUR, &destination, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_INGRESS_SRC_1MIN, &source, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_INGRESS_SRC_10MIN, &source, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_INGRESS_SRC_1HOUR, &source, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_INGRESS_DST_1MIN, &destination, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_INGRESS_DST_10MIN, &destination, event, now);
|
||||
ipv4_update_flow_stats(&IPV4_INGRESS_DST_1HOUR, &destination, event, now);
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,12 +62,12 @@ pub fn ipv6_update_stats(event: &IPv6Event) {
|
||||
let now = bpf_ktime_get_ns();
|
||||
let source = [event.source_ip, event.source_port as u128];
|
||||
let destination = [event.destination_ip, event.destination_port as u128];
|
||||
ipv6_update_flow_status(&IPV6_SRC_1MIN, &source, event, now);
|
||||
ipv6_update_flow_status(&IPV6_SRC_10MIN, &source, event, now);
|
||||
ipv6_update_flow_status(&IPV6_SRC_1HOUR, &source, event, now);
|
||||
ipv6_update_flow_status(&IPV6_DST_1MIN, &destination, event, now);
|
||||
ipv6_update_flow_status(&IPV6_DST_10MIN, &destination, event, now);
|
||||
ipv6_update_flow_status(&IPV6_DST_1HOUR, &destination, event, now);
|
||||
ipv6_update_flow_status(&IPV6_INGRESS_SRC_1MIN, &source, event, now);
|
||||
ipv6_update_flow_status(&IPV6_INGRESS_SRC_10MIN, &source, event, now);
|
||||
ipv6_update_flow_status(&IPV6_INGRESS_SRC_1HOUR, &source, event, now);
|
||||
ipv6_update_flow_status(&IPV6_INGRESS_DST_1MIN, &destination, event, now);
|
||||
ipv6_update_flow_status(&IPV6_INGRESS_DST_10MIN, &destination, event, now);
|
||||
ipv6_update_flow_status(&IPV6_INGRESS_DST_1HOUR, &destination, event, now);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,25 +23,23 @@ impl ConfigManager {
|
||||
}
|
||||
|
||||
fn load_config() -> anyhow::Result<Config> {
|
||||
match fs::read_to_string("./config.toml") {
|
||||
Ok(toml_string) => match toml::from_str::<ConfigTable>(&toml_string) {
|
||||
Ok(config_table) => {
|
||||
let config = config_table.config;
|
||||
if !Self::validate(&config) {
|
||||
error!("{}", SystemEntry::InvalidConfig);
|
||||
Err(anyhow!(SystemEntry::InvalidConfig))
|
||||
} else {
|
||||
Ok(config)
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
error!("{}", SystemEntry::InvalidConfig);
|
||||
Err(anyhow!(SystemEntry::InvalidConfig))
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
error!("{}", SystemEntry::ConfigNotFound);
|
||||
let parse_result = (|| {
|
||||
let toml_string = fs::read_to_string("./config.toml")
|
||||
.map_err(|_| anyhow!(SystemEntry::ConfigNotFound))?;
|
||||
let config_table = toml::from_str::<ConfigTable>(&toml_string)
|
||||
.map_err(|_| anyhow!(SystemEntry::InvalidConfig))?;
|
||||
let config = config_table.config;
|
||||
if !Self::validate(&config) {
|
||||
Err(anyhow!(SystemEntry::InvalidConfig))
|
||||
} else {
|
||||
Ok(config)
|
||||
}
|
||||
})();
|
||||
match parse_result {
|
||||
Ok(config) => Ok(config),
|
||||
Err(err) => {
|
||||
error!("{}", SystemEntry::InvalidConfig);
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -60,6 +58,7 @@ impl ConfigManager {
|
||||
once_lock.read().await.clone()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub async fn update(config: Config) {
|
||||
// Initialization has been ensured
|
||||
let lock = SYNC_CONFIG.get().unwrap();
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use crate::core::system::System;
|
||||
use crate::model::direction::Direction;
|
||||
use crate::model::ip_address::IpAddressType;
|
||||
use crate::model::direction::FlowDirection;
|
||||
use crate::model::ip_address::IntoNative;
|
||||
use crate::model::list_type::ListType;
|
||||
use crate::utils::ip_address::convert_ports_to_vec;
|
||||
use crate::utils::log_entry::ebpf::EbpfEntry;
|
||||
@ -18,26 +18,26 @@ use tracing::info;
|
||||
static ACCESS_CONTROL: OnceLock<RwLock<AccessControl>> = OnceLock::new();
|
||||
|
||||
pub struct AccessControl {
|
||||
ipv4_maps: StdHashMap<(Direction, ListType), AccessMap<IPv4>>,
|
||||
ipv6_maps: StdHashMap<(Direction, ListType), AccessMap<IPv6>>,
|
||||
ipv4_maps: StdHashMap<(FlowDirection, ListType), AccessMap<IPv4>>,
|
||||
ipv6_maps: StdHashMap<(FlowDirection, ListType), AccessMap<IPv6>>,
|
||||
}
|
||||
|
||||
impl AccessControl {
|
||||
const MAP_CONFIGS: [((Direction, ListType), (&'static str, &'static str)); 4] = [
|
||||
const MAP_CONFIGS: [((FlowDirection, ListType), (&'static str, &'static str)); 4] = [
|
||||
(
|
||||
(Direction::Source, ListType::White),
|
||||
(FlowDirection::Source, ListType::White),
|
||||
("IPV4_SRC_WHITELIST", "IPV6_SRC_WHITELIST"),
|
||||
),
|
||||
(
|
||||
(Direction::Source, ListType::Black),
|
||||
(FlowDirection::Source, ListType::Black),
|
||||
("IPV4_SRC_BLACKLIST", "IPV6_SRC_BLACKLIST"),
|
||||
),
|
||||
(
|
||||
(Direction::Destination, ListType::White),
|
||||
(FlowDirection::Destination, ListType::White),
|
||||
("IPV4_DST_WHITELIST", "IPV6_DST_WHITELIST"),
|
||||
),
|
||||
(
|
||||
(Direction::Destination, ListType::Black),
|
||||
(FlowDirection::Destination, ListType::Black),
|
||||
("IPV4_DST_BLACKLIST", "IPV6_DST_BLACKLIST"),
|
||||
),
|
||||
];
|
||||
@ -85,7 +85,7 @@ impl AccessControl {
|
||||
}
|
||||
|
||||
pub async fn get_ipv4_list(
|
||||
direction: Direction,
|
||||
direction: FlowDirection,
|
||||
list_type: ListType,
|
||||
) -> StdHashMap<Ipv4Addr, Vec<Port>> {
|
||||
let access_list = AccessControl::instance().await;
|
||||
@ -97,7 +97,7 @@ impl AccessControl {
|
||||
}
|
||||
|
||||
pub async fn get_ipv6_list(
|
||||
direction: Direction,
|
||||
direction: FlowDirection,
|
||||
list_type: ListType,
|
||||
) -> StdHashMap<Ipv6Addr, Vec<Port>> {
|
||||
let access_list = AccessControl::instance().await;
|
||||
@ -109,7 +109,7 @@ impl AccessControl {
|
||||
}
|
||||
|
||||
pub async fn add_ipv4_list(
|
||||
direction: Direction,
|
||||
direction: FlowDirection,
|
||||
list_type: ListType,
|
||||
address: SocketAddrV4,
|
||||
) -> anyhow::Result<()> {
|
||||
@ -124,7 +124,7 @@ impl AccessControl {
|
||||
}
|
||||
|
||||
pub async fn add_ipv6_list(
|
||||
direction: Direction,
|
||||
direction: FlowDirection,
|
||||
list_type: ListType,
|
||||
address: SocketAddrV6,
|
||||
) -> anyhow::Result<()> {
|
||||
@ -139,7 +139,7 @@ impl AccessControl {
|
||||
}
|
||||
|
||||
pub async fn remove_ipv4_list(
|
||||
direction: Direction,
|
||||
direction: FlowDirection,
|
||||
list_type: ListType,
|
||||
address: SocketAddrV4,
|
||||
) -> anyhow::Result<()> {
|
||||
@ -154,7 +154,7 @@ impl AccessControl {
|
||||
}
|
||||
|
||||
pub async fn remove_ipv6_list(
|
||||
direction: Direction,
|
||||
direction: FlowDirection,
|
||||
list_type: ListType,
|
||||
address: SocketAddrV6,
|
||||
) -> anyhow::Result<()> {
|
||||
@ -173,7 +173,7 @@ struct AccessMap<T> {
|
||||
map: AyaHashMap<MapData, T, [Port; MAX_RULES_PORT]>,
|
||||
}
|
||||
|
||||
impl<T: IpAddressType + Pod> AccessMap<T> {
|
||||
impl<T: IntoNative + Pod> AccessMap<T> {
|
||||
fn get_list(&self) -> StdHashMap<T::Native, Vec<Port>> {
|
||||
self.map
|
||||
.iter()
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use crate::core::system::System;
|
||||
use crate::model::direction::Direction;
|
||||
use crate::model::direction::{Direction, FlowDirection};
|
||||
use crate::model::flow_stats::FlowStats;
|
||||
use crate::model::ip_address::SocketAddressType;
|
||||
use crate::model::ip_address::IntoNative;
|
||||
use crate::model::time_type::TimeType;
|
||||
use crate::utils::log_entry::system::SystemEntry;
|
||||
use aya::maps::{HashMap as AyaHashMap, MapData};
|
||||
@ -18,38 +18,62 @@ static STATISTICS: OnceLock<RwLock<Statistics>> = OnceLock::new();
|
||||
|
||||
pub struct Statistics {
|
||||
terminate: bool,
|
||||
ipv4_maps: StdHashMap<(Direction, TimeType), FlowMap<EbpfAddrPortV4>>,
|
||||
ipv6_maps: StdHashMap<(Direction, TimeType), FlowMap<EbpfAddrPortV6>>,
|
||||
ipv4_maps: StdHashMap<(Direction, FlowDirection, TimeType), FlowMap<EbpfAddrPortV4>>,
|
||||
ipv6_maps: StdHashMap<(Direction, FlowDirection, TimeType), FlowMap<EbpfAddrPortV6>>,
|
||||
}
|
||||
|
||||
impl Statistics {
|
||||
const INGRESS_MAPS: [((Direction, TimeType), (&'static str, &'static str)); 3] = [
|
||||
const INGRESS_MAPS: [((Direction, FlowDirection, TimeType), (&'static str, &'static str)); 6] = [
|
||||
(
|
||||
(Direction::Source, TimeType::_1Min),
|
||||
("IPV4_SRC_1MIN", "IPV6_SRC_1MIN"),
|
||||
(Direction::Ingress, FlowDirection::Source, TimeType::_1Min),
|
||||
("IPV4_INGRESS_SRC_1MIN", "IPV6_INGRESS_SRC_1MIN"),
|
||||
),
|
||||
(
|
||||
(Direction::Source, TimeType::_10Min),
|
||||
("IPV4_SRC_10MIN", "IPV6_SRC_10MIN"),
|
||||
(Direction::Ingress, FlowDirection::Source, TimeType::_10Min),
|
||||
("IPV4_INGRESS_SRC_10MIN", "IPV6_INGRESS_SRC_10MIN"),
|
||||
),
|
||||
(
|
||||
(Direction::Source, TimeType::_1Hour),
|
||||
("IPV4_SRC_1HOUR", "IPV6_SRC_1HOUR"),
|
||||
(Direction::Ingress, FlowDirection::Source, TimeType::_1Hour),
|
||||
("IPV4_INGRESS_SRC_1HOUR", "IPV6_INGRESS_SRC_1HOUR"),
|
||||
),
|
||||
(
|
||||
(Direction::Ingress, FlowDirection::Destination, TimeType::_1Min),
|
||||
("IPV4_INGRESS_DST_1MIN", "IPV6_INGRESS_DST_1MIN"),
|
||||
),
|
||||
(
|
||||
(Direction::Ingress, FlowDirection::Destination, TimeType::_10Min),
|
||||
("IPV4_INGRESS_DST_10MIN", "IPV6_INGRESS_DST_10MIN"),
|
||||
),
|
||||
(
|
||||
(Direction::Ingress, FlowDirection::Destination, TimeType::_1Hour),
|
||||
("IPV4_INGRESS_DST_1HOUR", "IPV6_INGRESS_DST_1HOUR"),
|
||||
),
|
||||
];
|
||||
|
||||
const EGRESS_MAPS: [((Direction, TimeType), (&'static str, &'static str)); 3] = [
|
||||
const EGRESS_MAPS: [((Direction, FlowDirection, TimeType), (&'static str, &'static str)); 6] = [
|
||||
(
|
||||
(Direction::Destination, TimeType::_1Min),
|
||||
("IPV4_DST_1MIN", "IPV6_DST_1MIN"),
|
||||
(Direction::Egress, FlowDirection::Source, TimeType::_1Min),
|
||||
("IPV4_EGRESS_SRC_1MIN", "IPV6_EGRESS_SRC_1MIN"),
|
||||
),
|
||||
(
|
||||
(Direction::Destination, TimeType::_10Min),
|
||||
("IPV4_DST_10MIN", "IPV6_DST_10MIN"),
|
||||
(Direction::Egress, FlowDirection::Source, TimeType::_10Min),
|
||||
("IPV4_EGRESS_SRC_10MIN", "IPV6_EGRESS_SRC_10MIN"),
|
||||
),
|
||||
(
|
||||
(Direction::Destination, TimeType::_1Hour),
|
||||
("IPV4_DST_1HOUR", "IPV6_DST_1HOUR"),
|
||||
(Direction::Egress, FlowDirection::Source, TimeType::_1Hour),
|
||||
("IPV4_EGRESS_SRC_1HOUR", "IPV6_EGRESS_SRC_1HOUR"),
|
||||
),
|
||||
(
|
||||
(Direction::Egress, FlowDirection::Destination, TimeType::_1Min),
|
||||
("IPV4_EGRESS_DST_1MIN", "IPV6_EGRESS_DST_1MIN"),
|
||||
),
|
||||
(
|
||||
(Direction::Egress, FlowDirection::Destination, TimeType::_10Min),
|
||||
("IPV4_EGRESS_DST_10MIN", "IPV6_EGRESS_DST_10MIN"),
|
||||
),
|
||||
(
|
||||
(Direction::Egress, FlowDirection::Destination, TimeType::_1Hour),
|
||||
("IPV4_EGRESS_DST_1HOUR", "IPV6_EGRESS_DST_1HOUR"),
|
||||
),
|
||||
];
|
||||
|
||||
@ -88,12 +112,12 @@ impl Statistics {
|
||||
},
|
||||
);
|
||||
}
|
||||
let monitor = Statistics {
|
||||
let statistics = Statistics {
|
||||
terminate: false,
|
||||
ipv4_maps,
|
||||
ipv6_maps,
|
||||
};
|
||||
STATISTICS.get_or_init(|| RwLock::new(monitor));
|
||||
STATISTICS.get_or_init(|| RwLock::new(statistics));
|
||||
info!("{}", SystemEntry::InitializeComplete);
|
||||
Ok(())
|
||||
}
|
||||
@ -124,47 +148,49 @@ impl Statistics {
|
||||
}
|
||||
|
||||
pub async fn terminate() {
|
||||
let mut monitor = Statistics::instance_mut().await;
|
||||
monitor.terminate = true;
|
||||
let mut statistics = Statistics::instance_mut().await;
|
||||
statistics.terminate = true;
|
||||
}
|
||||
|
||||
pub async fn cleanup_expired_flows() {
|
||||
let mut monitor = Statistics::instance_mut().await;
|
||||
let mut statistics = Statistics::instance_mut().await;
|
||||
let boot_time = System::boot_time().await;
|
||||
let now = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos() as u64;
|
||||
monitor
|
||||
statistics
|
||||
.ipv4_maps
|
||||
.iter_mut()
|
||||
.for_each(|((_, time_type), map)| map.cleanup(boot_time, now, time_type.duration()));
|
||||
monitor
|
||||
.for_each(|((_, _, time_type), map)| map.cleanup(boot_time, now, time_type.duration()));
|
||||
statistics
|
||||
.ipv6_maps
|
||||
.iter_mut()
|
||||
.for_each(|((_, time_type), map)| map.cleanup(boot_time, now, time_type.duration()));
|
||||
.for_each(|((_, _, time_type), map)| map.cleanup(boot_time, now, time_type.duration()));
|
||||
}
|
||||
|
||||
pub async fn get_ipv4_flow_data(
|
||||
direction: Direction,
|
||||
flow_direction: FlowDirection,
|
||||
time_type: TimeType,
|
||||
) -> StdHashMap<SocketAddrV4, FlowStats> {
|
||||
let monitor = Statistics::instance().await;
|
||||
monitor
|
||||
let statistics = Statistics::instance().await;
|
||||
statistics
|
||||
.ipv4_maps
|
||||
.get(&(direction, time_type))
|
||||
.get(&(direction, flow_direction, time_type))
|
||||
.map(|map| map.get_map())
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub async fn get_ipv6_flow_data(
|
||||
direction: Direction,
|
||||
flow_direction: FlowDirection,
|
||||
time_type: TimeType,
|
||||
) -> StdHashMap<SocketAddrV6, FlowStats> {
|
||||
let monitor = Statistics::instance().await;
|
||||
monitor
|
||||
let statistics = Statistics::instance().await;
|
||||
statistics
|
||||
.ipv6_maps
|
||||
.get(&(direction, time_type))
|
||||
.get(&(direction, flow_direction, time_type))
|
||||
.map(|map| map.get_map())
|
||||
.unwrap()
|
||||
}
|
||||
@ -174,7 +200,7 @@ struct FlowMap<T> {
|
||||
map: AyaHashMap<MapData, T, EbpfFlowStats>,
|
||||
}
|
||||
|
||||
impl<T: SocketAddressType + Pod> FlowMap<T> {
|
||||
impl<T: IntoNative + Pod> FlowMap<T> {
|
||||
fn get_map(&self) -> StdHashMap<T::Native, FlowStats> {
|
||||
self.map
|
||||
.iter()
|
||||
|
||||
@ -46,31 +46,9 @@ impl System {
|
||||
let egress_interface = config.egress_ifindex;
|
||||
let boot_time = SystemInfo::boot_time() * 1_000_000_000;
|
||||
Self::set_memory_limit()?;
|
||||
let mut ingress_ebpf = Ebpf::load(aya::include_bytes_aligned!(concat!(
|
||||
env!("OUT_DIR"),
|
||||
"/net-guardia-ingress"
|
||||
)))?;
|
||||
let mut egress_ebpf = Ebpf::load(aya::include_bytes_aligned!(concat!(
|
||||
env!("OUT_DIR"),
|
||||
"/net-guardia-egress"
|
||||
)))?;
|
||||
if let Err(e) = aya_log::EbpfLogger::init(&mut ingress_ebpf) {
|
||||
error!("{}", e);
|
||||
warn!("{}", EbpfEntry::LoggerInitializeFailed);
|
||||
}
|
||||
if let Err(e) = aya_log::EbpfLogger::init(&mut egress_ebpf) {
|
||||
error!("{}", e);
|
||||
warn!("{}", EbpfEntry::LoggerInitializeFailed);
|
||||
}
|
||||
let mut ingress_program_array = ProgramArray::try_from(ingress_ebpf.take_map("PROGRAM_ARRAY").unwrap())?;
|
||||
Self::load_program(&mut ingress_ebpf, &mut ingress_program_array, "access_control", 0)?;
|
||||
Self::load_program(&mut ingress_ebpf, &mut ingress_program_array, "service", 1)?;
|
||||
// Self::load_program(&mut ebpf, &mut ingress_program_array, "defence", 2)?;
|
||||
Self::load_program(&mut ingress_ebpf, &mut ingress_program_array, "sampling", 3)?;
|
||||
Self::load_program(&mut ingress_ebpf, &mut ingress_program_array, "statistics", 4)?;
|
||||
let (mut ingress_ebpf, ingress_program_array) = System::get_ingress_ebpf()?;
|
||||
let ingress_program: &mut Xdp = ingress_ebpf.program_mut("net_guardia").unwrap().try_into()?;
|
||||
let mut egress_program_array = ProgramArray::try_from(egress_ebpf.take_map("PROGRAM_ARRAY").unwrap())?;
|
||||
Self::load_program(&mut egress_ebpf, &mut egress_program_array, "statistics", 0)?;
|
||||
let (mut egress_ebpf, egress_program_array) = System::get_egress_ebpf()?;
|
||||
let egress_program: &mut Xdp = egress_ebpf.program_mut("net_guardia").unwrap().try_into()?;
|
||||
ingress_program.load()?;
|
||||
ingress_program
|
||||
@ -92,6 +70,38 @@ impl System {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_ingress_ebpf() -> anyhow::Result<(Ebpf, ProgramArray<MapData>)> {
|
||||
let mut ingress_ebpf = Ebpf::load(aya::include_bytes_aligned!(concat!(
|
||||
env!("OUT_DIR"),
|
||||
"/net-guardia-ingress"
|
||||
)))?;
|
||||
if let Err(e) = aya_log::EbpfLogger::init(&mut ingress_ebpf) {
|
||||
error!("{}", e);
|
||||
warn!("{}", EbpfEntry::LoggerInitializeFailed);
|
||||
}
|
||||
let mut ingress_program_array = ProgramArray::try_from(ingress_ebpf.take_map("PROGRAM_ARRAY").unwrap())?;
|
||||
Self::load_program(&mut ingress_ebpf, &mut ingress_program_array, "access_control", 0)?;
|
||||
Self::load_program(&mut ingress_ebpf, &mut ingress_program_array, "service", 1)?;
|
||||
// Self::load_program(&mut ebpf, &mut ingress_program_array, "defence", 2)?;
|
||||
Self::load_program(&mut ingress_ebpf, &mut ingress_program_array, "sampling", 3)?;
|
||||
Self::load_program(&mut ingress_ebpf, &mut ingress_program_array, "statistics", 4)?;
|
||||
Ok((ingress_ebpf, ingress_program_array))
|
||||
}
|
||||
|
||||
fn get_egress_ebpf() -> anyhow::Result<(Ebpf, ProgramArray<MapData>)> {
|
||||
let mut egress_ebpf = Ebpf::load(aya::include_bytes_aligned!(concat!(
|
||||
env!("OUT_DIR"),
|
||||
"/net-guardia-egress"
|
||||
)))?;
|
||||
if let Err(e) = aya_log::EbpfLogger::init(&mut egress_ebpf) {
|
||||
error!("{}", e);
|
||||
warn!("{}", EbpfEntry::LoggerInitializeFailed);
|
||||
}
|
||||
let mut egress_program_array = ProgramArray::try_from(egress_ebpf.take_map("PROGRAM_ARRAY").unwrap())?;
|
||||
Self::load_program(&mut egress_ebpf, &mut egress_program_array, "statistics", 0)?;
|
||||
Ok((egress_ebpf, egress_program_array))
|
||||
}
|
||||
|
||||
fn set_memory_limit() -> anyhow::Result<()> {
|
||||
let rlim = libc::rlimit {
|
||||
rlim_cur: libc::RLIM_INFINITY,
|
||||
|
||||
@ -3,6 +3,13 @@ use serde::{Deserialize, Serialize};
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Direction {
|
||||
Ingress,
|
||||
Egress,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Hash)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum FlowDirection {
|
||||
Source,
|
||||
Destination,
|
||||
}
|
||||
|
||||
@ -2,62 +2,39 @@ use net_guardia_common::model::ip_address::{IPv4, IPv6, EbpfAddrPortV4, EbpfAddr
|
||||
use std::hash::Hash;
|
||||
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6};
|
||||
|
||||
pub trait IpAddressType: Copy {
|
||||
pub trait IntoNative: Copy {
|
||||
type Native: Eq + PartialEq + Hash;
|
||||
fn into_native(self) -> Self::Native;
|
||||
fn from_native(native: Self::Native) -> Self;
|
||||
}
|
||||
|
||||
impl IpAddressType for IPv4 {
|
||||
impl IntoNative for IPv4 {
|
||||
type Native = Ipv4Addr;
|
||||
|
||||
fn into_native(self) -> Self::Native {
|
||||
Ipv4Addr::from(self)
|
||||
}
|
||||
|
||||
fn from_native(native: Self::Native) -> Self {
|
||||
native.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl IpAddressType for IPv6 {
|
||||
impl IntoNative for IPv6 {
|
||||
type Native = Ipv6Addr;
|
||||
|
||||
fn into_native(self) -> Self::Native {
|
||||
Ipv6Addr::from(self)
|
||||
}
|
||||
|
||||
fn from_native(native: Self::Native) -> Self {
|
||||
native.into()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SocketAddressType: Copy {
|
||||
type Native: Eq + PartialEq + Hash;
|
||||
fn into_native(self) -> Self::Native;
|
||||
fn from_native(native: Self::Native) -> Self;
|
||||
}
|
||||
|
||||
impl SocketAddressType for EbpfAddrPortV4 {
|
||||
impl IntoNative for EbpfAddrPortV4 {
|
||||
type Native = SocketAddrV4;
|
||||
|
||||
fn into_native(self) -> Self::Native {
|
||||
SocketAddrV4::new(Ipv4Addr::from(self[0]), self[1] as u16)
|
||||
}
|
||||
|
||||
fn from_native(native: Self::Native) -> Self {
|
||||
[(*native.ip()).into(), native.port() as u32]
|
||||
}
|
||||
}
|
||||
|
||||
impl SocketAddressType for EbpfAddrPortV6 {
|
||||
impl IntoNative for EbpfAddrPortV6 {
|
||||
type Native = SocketAddrV6;
|
||||
|
||||
fn into_native(self) -> Self::Native {
|
||||
SocketAddrV6::new(Ipv6Addr::from(self[0]), self[1] as u16, 0, 0)
|
||||
}
|
||||
|
||||
fn from_native(native: Self::Native) -> Self {
|
||||
[(*native.ip()).into(), native.port() as u128]
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::core::control::access_control::AccessControl;
|
||||
use crate::model::direction::Direction;
|
||||
use crate::model::direction::FlowDirection;
|
||||
use crate::model::list_type::ListType;
|
||||
use actix_web::{delete, get, put, web, HttpResponse, Responder, Scope};
|
||||
use std::net::{SocketAddrV4, SocketAddrV6};
|
||||
@ -15,21 +15,21 @@ pub fn initialize() -> Scope {
|
||||
}
|
||||
|
||||
#[get("/ipv4/{direction}/{list_type}")]
|
||||
async fn get_ipv4_list(path: web::Path<(Direction, ListType)>) -> impl Responder {
|
||||
async fn get_ipv4_list(path: web::Path<(FlowDirection, ListType)>) -> impl Responder {
|
||||
let (direction, list_type) = path.into_inner();
|
||||
let list = AccessControl::get_ipv4_list(direction, list_type).await;
|
||||
HttpResponse::Ok().json(list)
|
||||
}
|
||||
|
||||
#[get("/ipv6/{direction}/{list_type}")]
|
||||
async fn get_ipv6_list(path: web::Path<(Direction, ListType)>) -> impl Responder {
|
||||
async fn get_ipv6_list(path: web::Path<(FlowDirection, ListType)>) -> impl Responder {
|
||||
let (direction, list_type) = path.into_inner();
|
||||
let list = AccessControl::get_ipv6_list(direction, list_type).await;
|
||||
HttpResponse::Ok().json(list)
|
||||
}
|
||||
|
||||
#[put("/ipv4/{direction}/{list_type}")]
|
||||
async fn add_ipv4_list(address: web::Json<SocketAddrV4>, path: web::Path<(Direction, ListType)>) -> impl Responder {
|
||||
async fn add_ipv4_list(address: web::Json<SocketAddrV4>, path: web::Path<(FlowDirection, ListType)>) -> impl Responder {
|
||||
let address = address.into_inner();
|
||||
let (direction, list_type) = path.into_inner();
|
||||
match AccessControl::add_ipv4_list(direction, list_type, address).await {
|
||||
@ -39,7 +39,7 @@ async fn add_ipv4_list(address: web::Json<SocketAddrV4>, path: web::Path<(Direct
|
||||
}
|
||||
|
||||
#[put("/ipv6/{direction}/{list_type}")]
|
||||
async fn add_ipv6_list(address: web::Json<SocketAddrV6>, path: web::Path<(Direction, ListType)>) -> impl Responder {
|
||||
async fn add_ipv6_list(address: web::Json<SocketAddrV6>, path: web::Path<(FlowDirection, ListType)>) -> impl Responder {
|
||||
let address = address.into_inner();
|
||||
let (direction, list_type) = path.into_inner();
|
||||
match AccessControl::add_ipv6_list(direction, list_type, address).await {
|
||||
@ -49,7 +49,7 @@ async fn add_ipv6_list(address: web::Json<SocketAddrV6>, path: web::Path<(Direct
|
||||
}
|
||||
|
||||
#[delete("/ipv4/{direction}/{list_type}")]
|
||||
async fn remove_ipv4_list(address: web::Json<SocketAddrV4>, path: web::Path<(Direction, ListType)>) -> impl Responder {
|
||||
async fn remove_ipv4_list(address: web::Json<SocketAddrV4>, path: web::Path<(FlowDirection, ListType)>) -> impl Responder {
|
||||
let address = address.into_inner();
|
||||
let (direction, list_type) = path.into_inner();
|
||||
match AccessControl::remove_ipv4_list(direction, list_type, address).await {
|
||||
@ -59,7 +59,7 @@ async fn remove_ipv4_list(address: web::Json<SocketAddrV4>, path: web::Path<(Dir
|
||||
}
|
||||
|
||||
#[delete("/ipv6/{direction}/{list_type}")]
|
||||
async fn remove_ipv6_list(address: web::Json<SocketAddrV6>, path: web::Path<(Direction, ListType)>) -> impl Responder {
|
||||
async fn remove_ipv6_list(address: web::Json<SocketAddrV6>, path: web::Path<(FlowDirection, ListType)>) -> impl Responder {
|
||||
let address = address.into_inner();
|
||||
let (direction, list_type) = path.into_inner();
|
||||
match AccessControl::remove_ipv6_list(direction, list_type, address).await {
|
||||
|
||||
@ -2,7 +2,7 @@ use crate::core::statistics::Statistics;
|
||||
use crate::web::utils::flow_websocket::{IPv4FlowWebSocket, IPv6FlowWebSocket};
|
||||
use actix_web::{get, web, Error, HttpRequest, HttpResponse, Responder, Scope};
|
||||
use actix_web_actors::ws::start;
|
||||
use crate::model::direction::Direction;
|
||||
use crate::model::direction::{Direction, FlowDirection};
|
||||
use crate::model::time_type::TimeType;
|
||||
|
||||
pub fn initialize() -> Scope {
|
||||
@ -13,45 +13,46 @@ pub fn initialize() -> Scope {
|
||||
.service(websocket_ipv6)
|
||||
}
|
||||
|
||||
#[get("/get/ipv4/{direction}/{time_type}")]
|
||||
async fn get_ipv4_flow(path: web::Path<(Direction, TimeType)>) -> impl Responder {
|
||||
let (direction, time_type) = path.into_inner();
|
||||
let flow_data = Statistics::get_ipv4_flow_data(direction, time_type).await;
|
||||
#[get("/get/ipv4/{direction}/{flow_direction}/{time_type}")]
|
||||
async fn get_ipv4_flow(path: web::Path<(Direction, FlowDirection, TimeType)>) -> impl Responder {
|
||||
let (direction, flow_direction, time_type) = path.into_inner();
|
||||
let flow_data = Statistics::get_ipv4_flow_data(direction, flow_direction, time_type).await;
|
||||
HttpResponse::Ok().json(web::Json(flow_data))
|
||||
}
|
||||
|
||||
|
||||
#[get("/get/ipv6/{direction}/{time_type}")]
|
||||
async fn get_ipv6_flow(path: web::Path<(Direction, TimeType)>) -> impl Responder {
|
||||
let (direction, time_type) = path.into_inner();
|
||||
let flow_data = Statistics::get_ipv6_flow_data(direction, time_type).await;
|
||||
#[get("/get/ipv6/{direction}/{flow_direction}/{time_type}")]
|
||||
async fn get_ipv6_flow(path: web::Path<(Direction, FlowDirection, TimeType)>) -> impl Responder {
|
||||
let (direction, flow_direction, time_type) = path.into_inner();
|
||||
let flow_data = Statistics::get_ipv6_flow_data(direction, flow_direction, time_type).await;
|
||||
HttpResponse::Ok().json(web::Json(flow_data))
|
||||
}
|
||||
|
||||
#[get("/websocket/ipv4/{direction}/{time_type}")]
|
||||
#[get("/websocket/ipv4/{direction}/{flow_direction}/{time_type}")]
|
||||
async fn websocket_ipv4(
|
||||
req: HttpRequest,
|
||||
stream: web::Payload,
|
||||
path: web::Path<(Direction, TimeType)>,
|
||||
path: web::Path<(Direction, FlowDirection, TimeType)>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
let (direction, time_type) = path.into_inner();
|
||||
let (direction, flow_direction, time_type) = path.into_inner();
|
||||
let websocket = IPv4FlowWebSocket {
|
||||
direction,
|
||||
flow_direction,
|
||||
time_type,
|
||||
interval: None,
|
||||
};
|
||||
start(websocket, &req, stream)
|
||||
}
|
||||
|
||||
#[get("/websocket/ipv6/{direction}/{time_type}")]
|
||||
#[get("/websocket/ipv6/{direction}/{flow_direction}/{time_type}")]
|
||||
async fn websocket_ipv6(
|
||||
req: HttpRequest,
|
||||
stream: web::Payload,
|
||||
path: web::Path<(Direction, TimeType)>,
|
||||
path: web::Path<(Direction, FlowDirection, TimeType)>,
|
||||
) -> Result<HttpResponse, Error> {
|
||||
let (direction, time_type) = path.into_inner();
|
||||
let (direction, flow_direction, time_type) = path.into_inner();
|
||||
let websocket = IPv6FlowWebSocket {
|
||||
direction,
|
||||
flow_direction,
|
||||
time_type,
|
||||
interval: None,
|
||||
};
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
use crate::core::config_manager::ConfigManager;
|
||||
use crate::core::statistics::Statistics;
|
||||
use crate::model::direction::{Direction, FlowDirection};
|
||||
use crate::model::time_type::TimeType;
|
||||
use actix::prelude::*;
|
||||
use actix_web_actors::ws;
|
||||
use std::time::Duration;
|
||||
use crate::model::direction::Direction;
|
||||
use crate::model::time_type::TimeType;
|
||||
|
||||
pub struct IPv4FlowWebSocket {
|
||||
pub direction: Direction,
|
||||
pub flow_direction: FlowDirection,
|
||||
pub time_type: TimeType,
|
||||
pub interval: Option<SpawnHandle>,
|
||||
}
|
||||
@ -20,8 +21,11 @@ impl Actor for IPv4FlowWebSocket {
|
||||
let refresh_interval = Duration::from_secs(config.refresh_interval);
|
||||
let interval = ctx.run_interval(refresh_interval, |actor, ctx| {
|
||||
let direction = actor.direction.clone();
|
||||
let flow_direction = actor.flow_direction.clone();
|
||||
let time_type = actor.time_type.clone();
|
||||
let future = async move { Statistics::get_ipv4_flow_data(direction, time_type).await };
|
||||
let future = async move {
|
||||
Statistics::get_ipv4_flow_data(direction, flow_direction, time_type).await
|
||||
};
|
||||
ctx.wait(future.into_actor(actor).map(|flow_data, _, ctx| {
|
||||
if let Ok(json) = serde_json::to_string(&flow_data) {
|
||||
ctx.text(json);
|
||||
@ -54,6 +58,7 @@ impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for IPv4FlowWebSocket
|
||||
|
||||
pub struct IPv6FlowWebSocket {
|
||||
pub direction: Direction,
|
||||
pub flow_direction: FlowDirection,
|
||||
pub time_type: TimeType,
|
||||
pub interval: Option<SpawnHandle>,
|
||||
}
|
||||
@ -66,8 +71,11 @@ impl Actor for IPv6FlowWebSocket {
|
||||
let refresh_interval = Duration::from_secs(config.refresh_interval);
|
||||
let interval = ctx.run_interval(refresh_interval, |actor, ctx| {
|
||||
let direction = actor.direction.clone();
|
||||
let flow_direction = actor.flow_direction.clone();
|
||||
let time_type = actor.time_type.clone();
|
||||
let future = async move { Statistics::get_ipv6_flow_data(direction, time_type).await };
|
||||
let future = async move {
|
||||
Statistics::get_ipv6_flow_data(direction, flow_direction, time_type).await
|
||||
};
|
||||
ctx.wait(future.into_actor(actor).map(|flow_data, _, ctx| {
|
||||
if let Ok(json) = serde_json::to_string(&flow_data) {
|
||||
ctx.text(json);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user