From c4598970a2985b336b8b50099547664c55d29b7c Mon Sep 17 00:00:00 2001 From: DaLaw2 Date: Sun, 31 Aug 2025 13:18:26 +0800 Subject: [PATCH] refactor: Refactor packet parsing and event handling for better speed (#5) --- net-guardia-common/src/ebpf/parsing.rs | 111 ++++++++++++------ net-guardia-common/src/model/event.rs | 81 ++----------- net-guardia-common/src/model/packet.rs | 42 +------ .../src/action/statistics.rs | 8 +- net-guardia-egress-ebpf/src/main.rs | 57 ++++----- .../src/action/service.rs | 12 +- .../src/action/statistics.rs | 11 +- .../src/action/transmission.rs | 21 ++-- net-guardia-ingress-ebpf/src/main.rs | 103 ++++++---------- net-guardia/src/core/system.rs | 3 +- 10 files changed, 179 insertions(+), 270 deletions(-) diff --git a/net-guardia-common/src/ebpf/parsing.rs b/net-guardia-common/src/ebpf/parsing.rs index 6554cc7..24592b6 100644 --- a/net-guardia-common/src/ebpf/parsing.rs +++ b/net-guardia-common/src/ebpf/parsing.rs @@ -1,5 +1,3 @@ -use crate::model::event::Event; -use crate::define::offset::*; use aya_ebpf::helpers::bpf_ktime_get_ns; use network_types::{ eth::{EthHdr, EtherType}, @@ -8,7 +6,12 @@ use network_types::{ udp::UdpHdr, }; -pub fn parse_packet(start: usize, end: usize) -> Result { +use crate::{ + define::offset::*, + model::event::{Event, IPv4Event, IPv6Event}, +}; + +pub fn parse_packet(start: usize, end: usize, target: *mut Event) -> Result<(), ()> { unsafe { if start + ETHER_HEADER_END > end { return Err(()); @@ -16,70 +19,112 @@ pub fn parse_packet(start: usize, end: usize) -> Result { let eth = &*((start + ETHER_HEADER_START) as *const EthHdr); let ether_type = eth.ether_type().map_err(|_| ())?; match ether_type { - EtherType::Ipv4 => parse_ipv4_packet(start, end), - EtherType::Ipv6 => parse_ipv6_packet(start, end), + EtherType::Ipv4 => parse_ipv4_packet(start, end, target), + EtherType::Ipv6 => parse_ipv6_packet(start, end, target), _ => Err(()), } } } #[inline(always)] -unsafe fn parse_ipv4_packet(start: usize, end: usize) -> Result { +unsafe fn parse_ipv4_packet(start: usize, end: usize, target: *mut Event) -> Result<(), ()> { unsafe { if start + IPV4_HEADER_END > end { return Err(()); } - let ipv4 = &*((start + IPV4_HEADER_START) as *const Ipv4Hdr); - let protocol = ipv4.proto; - let source_ip = u32::from_be_bytes(ipv4.src_addr); - let destination_ip = u32::from_be_bytes(ipv4.dst_addr); - let (source_port, destination_port) = match protocol { + let ipv4 = &*((start + IPV4_HEADER_START) as *const Ipv4Hdr); + + let (source_port, destination_port) = match ipv4.proto { IpProto::Tcp => parse_tcp_port(start, end, IPV4_TCP_HEADER_START, IPV4_TCP_HEADER_END)?, IpProto::Udp => parse_udp_port(start, end, IPV4_UDP_HEADER_START, IPV4_UDP_HEADER_END)?, _ => return Err(()), }; - Ok(Event { - eth_type: EtherType::Ipv4, - protocol, - source_ip: source_ip as u128, - destination_ip: destination_ip as u128, + *(target as *mut u32) = 0; + + let ipv4_data_ptr = (target as *mut u8).add(16); + + core::ptr::write(ipv4_data_ptr as *mut IpProto, ipv4.proto); + core::ptr::copy_nonoverlapping( + ipv4.src_addr.as_ptr(), + ipv4_data_ptr.add(core::mem::offset_of!(IPv4Event, source_ip)), + 4, + ); + core::ptr::copy_nonoverlapping( + ipv4.dst_addr.as_ptr(), + ipv4_data_ptr.add(core::mem::offset_of!(IPv4Event, destination_ip)), + 4, + ); + core::ptr::write( + ipv4_data_ptr.add(core::mem::offset_of!(IPv4Event, source_port)) as *mut u16, source_port, + ); + core::ptr::write( + ipv4_data_ptr.add(core::mem::offset_of!(IPv4Event, destination_port)) as *mut u16, destination_port, - len: (end - start) as u32, - timestamp: bpf_ktime_get_ns(), - }) + ); + core::ptr::write( + ipv4_data_ptr.add(core::mem::offset_of!(IPv4Event, len)) as *mut u32, + (end - start) as u32, + ); + core::ptr::write( + ipv4_data_ptr.add(core::mem::offset_of!(IPv4Event, timestamp)) as *mut u64, + bpf_ktime_get_ns(), + ); + + Ok(()) } } #[inline(always)] -unsafe fn parse_ipv6_packet(start: usize, end: usize) -> Result { +unsafe fn parse_ipv6_packet(start: usize, end: usize, target: *mut Event) -> Result<(), ()> { unsafe { if start + IPV6_HEADER_END > end { return Err(()); } - let ipv6 = &*((start + IPV6_HEADER_START) as *const Ipv6Hdr); - let protocol = ipv6.next_hdr; - let source_ip = u128::from_be_bytes(ipv6.src_addr); - let destination_ip = u128::from_be_bytes(ipv6.dst_addr); - let (source_port, destination_port) = match protocol { + let ipv6 = &*((start + IPV6_HEADER_START) as *const Ipv6Hdr); + + let (source_port, destination_port) = match ipv6.next_hdr { IpProto::Tcp => parse_tcp_port(start, end, IPV6_TCP_HEADER_START, IPV6_TCP_HEADER_END)?, IpProto::Udp => parse_udp_port(start, end, IPV6_UDP_HEADER_START, IPV6_UDP_HEADER_END)?, _ => return Err(()), }; - Ok(Event { - eth_type: EtherType::Ipv6, - protocol, - source_ip, - destination_ip, + *(target as *mut u32) = 1; + + let ipv6_data_ptr = (target as *mut u8).add(16); + + core::ptr::write(ipv6_data_ptr as *mut IpProto, ipv6.next_hdr); + core::ptr::copy_nonoverlapping( + ipv6.src_addr.as_ptr(), + ipv6_data_ptr.add(core::mem::offset_of!(IPv6Event, source_ip)), + 16, + ); + core::ptr::copy_nonoverlapping( + ipv6.dst_addr.as_ptr(), + ipv6_data_ptr.add(core::mem::offset_of!(IPv6Event, destination_ip)), + 16, + ); + core::ptr::write( + ipv6_data_ptr.add(core::mem::offset_of!(IPv6Event, source_port)) as *mut u16, source_port, + ); + core::ptr::write( + ipv6_data_ptr.add(core::mem::offset_of!(IPv6Event, destination_port)) as *mut u16, destination_port, - len: (end - start) as u32, - timestamp: bpf_ktime_get_ns(), - }) + ); + core::ptr::write( + ipv6_data_ptr.add(core::mem::offset_of!(IPv6Event, len)) as *mut u32, + (end - start) as u32, + ); + core::ptr::write( + ipv6_data_ptr.add(core::mem::offset_of!(IPv6Event, timestamp)) as *mut u64, + bpf_ktime_get_ns(), + ); + + Ok(()) } } diff --git a/net-guardia-common/src/model/event.rs b/net-guardia-common/src/model/event.rs index 78f4091..82ea285 100644 --- a/net-guardia-common/src/model/event.rs +++ b/net-guardia-common/src/model/event.rs @@ -1,72 +1,14 @@ -use crate::model::ip_address::{AddrPortV4, AddrPortV6}; -use network_types::eth::EtherType; use network_types::ip::IpProto; -pub struct Event { - pub eth_type: EtherType, - pub protocol: IpProto, - pub source_ip: u128, - pub destination_ip: u128, - pub source_port: u16, - pub destination_port: u16, - pub len: u32, - pub timestamp: u64, -} - -impl Event { - #[inline(always)] - pub fn to_ipv4_event(&self) -> IPv4Event { - IPv4Event { - protocol: self.protocol, - source_ip: self.source_ip as u32, - destination_ip: self.destination_ip as u32, - source_port: self.source_port, - destination_port: self.destination_port, - len: self.len, - timestamp: self.timestamp, - } - } - - #[inline(always)] - pub fn to_ipv6_event(&self) -> IPv6Event { - IPv6Event { - protocol: self.protocol, - source_ip: self.source_ip, - destination_ip: self.destination_ip, - source_port: self.source_port, - destination_port: self.destination_port, - len: self.len, - timestamp: self.timestamp, - } - } - - #[inline(always)] - pub fn into_ipv4_event(self) -> IPv4Event { - IPv4Event { - protocol: self.protocol, - source_ip: self.source_ip as u32, - destination_ip: self.destination_ip as u32, - source_port: self.source_port, - destination_port: self.destination_port, - len: self.len, - timestamp: self.timestamp, - } - } - - #[inline(always)] - pub fn into_ipv6_event(self) -> IPv6Event { - IPv6Event { - protocol: self.protocol, - source_ip: self.source_ip, - destination_ip: self.destination_ip, - source_port: self.source_port, - destination_port: self.destination_port, - len: self.len, - timestamp: self.timestamp, - } - } +use crate::model::ip_address::{AddrPortV4, AddrPortV6}; + +#[repr(C, align(8))] +pub enum Event { + IPv4(IPv4Event), + IPv6(IPv6Event), } +#[repr(C, align(8))] pub struct IPv4Event { pub protocol: IpProto, pub source_ip: u32, @@ -79,7 +21,7 @@ pub struct IPv4Event { impl IPv4Event { #[inline(always)] - pub fn get_source(&self) -> AddrPortV4 { + pub fn source_addr(&self) -> AddrPortV4 { AddrPortV4 { ip: self.source_ip, port: self.source_port, @@ -87,7 +29,7 @@ impl IPv4Event { } #[inline(always)] - pub fn get_destination(&self) -> AddrPortV4 { + pub fn destination_addr(&self) -> AddrPortV4 { AddrPortV4 { ip: self.destination_ip, port: self.destination_port, @@ -95,6 +37,7 @@ impl IPv4Event { } } +#[repr(C, align(8))] pub struct IPv6Event { pub protocol: IpProto, pub source_ip: u128, @@ -107,7 +50,7 @@ pub struct IPv6Event { impl IPv6Event { #[inline(always)] - pub fn get_source(&self) -> AddrPortV6 { + pub fn source_addr(&self) -> AddrPortV6 { AddrPortV6 { ip: self.source_ip, port: self.source_port, @@ -115,7 +58,7 @@ impl IPv6Event { } #[inline(always)] - pub fn get_destination(&self) -> AddrPortV6 { + pub fn destination_addr(&self) -> AddrPortV6 { AddrPortV6 { ip: self.destination_ip, port: self.destination_port, diff --git a/net-guardia-common/src/model/packet.rs b/net-guardia-common/src/model/packet.rs index 8850958..9a57280 100644 --- a/net-guardia-common/src/model/packet.rs +++ b/net-guardia-common/src/model/packet.rs @@ -1,6 +1,7 @@ -use crate::define::other::STANDARD_MTU; -use crate::model::event::{Event, IPv4Event, IPv6Event}; -use network_types::eth::EtherType; +use crate::{ + define::other::STANDARD_MTU, + model::event::Event, +}; #[repr(C, align(8))] pub struct Packet { @@ -10,39 +11,6 @@ pub struct Packet { impl Packet { pub fn new(event: Event, raw_data: [u8; STANDARD_MTU]) -> Self { - Self { - event, - raw_data, - } - } - - pub fn ether_type(&self) -> EtherType { - self.event.eth_type - } - - pub fn into_ipv4_packet(self) -> IPv4Packet { - IPv4Packet { - event: self.event.into_ipv4_event(), - raw_data: self.raw_data, - } - } - - pub fn into_ipv6_packet(self) -> IPv6Packet { - IPv6Packet { - event: self.event.into_ipv6_event(), - raw_data: self.raw_data, - } + Self { event, raw_data } } } - -#[repr(C, align(8))] -pub struct IPv4Packet { - pub event: IPv4Event, - pub raw_data: [u8; STANDARD_MTU], -} - -#[repr(C, align(8))] -pub struct IPv6Packet { - pub event: IPv6Event, - pub raw_data: [u8; STANDARD_MTU], -} diff --git a/net-guardia-egress-ebpf/src/action/statistics.rs b/net-guardia-egress-ebpf/src/action/statistics.rs index 5566139..9baef5a 100644 --- a/net-guardia-egress-ebpf/src/action/statistics.rs +++ b/net-guardia-egress-ebpf/src/action/statistics.rs @@ -32,8 +32,8 @@ static IPV6_INGRESS_DST_1HOUR: LruHashMap = LruHashMap::w pub fn ipv4_update_stats(event: &IPv4Event) { unsafe { - let source = event.get_source(); - let destination = event.get_destination(); + let source = event.source_addr(); + let destination = event.destination_addr(); ipv4_update_flow_stats(&IPV4_INGRESS_SRC_1MIN, &source, event); ipv4_update_flow_stats(&IPV4_INGRESS_SRC_10MIN, &source, event); ipv4_update_flow_stats(&IPV4_INGRESS_SRC_1HOUR, &source, event); @@ -45,8 +45,8 @@ pub fn ipv4_update_stats(event: &IPv4Event) { pub fn ipv6_update_stats(event: &IPv6Event) { unsafe { - let source = event.get_source(); - let destination = event.get_destination(); + let source = event.source_addr(); + let destination = event.destination_addr(); ipv6_update_flow_status(&IPV6_INGRESS_SRC_1MIN, &source, event); ipv6_update_flow_status(&IPV6_INGRESS_SRC_10MIN, &source, event); ipv6_update_flow_status(&IPV6_INGRESS_SRC_1HOUR, &source, event); diff --git a/net-guardia-egress-ebpf/src/main.rs b/net-guardia-egress-ebpf/src/main.rs index 0a945f5..1e91668 100644 --- a/net-guardia-egress-ebpf/src/main.rs +++ b/net-guardia-egress-ebpf/src/main.rs @@ -3,12 +3,14 @@ mod action; use action::statistics; -use aya_ebpf::macros::{map, xdp}; -use aya_ebpf::maps::{PerCpuArray, ProgramArray}; -use aya_ebpf::{bindings::xdp_action, programs::XdpContext}; +use aya_ebpf::{ + bindings::xdp_action, + macros::{map, xdp}, + maps::{PerCpuArray, ProgramArray}, + programs::XdpContext, +}; use aya_log_ebpf::error; -use net_guardia_common::ebpf::parsing; -use net_guardia_common::model::event::Event; +use net_guardia_common::{ebpf::parsing, model::event::Event}; use network_types::eth::EtherType; #[map] @@ -18,49 +20,38 @@ static PARSED_PACKET: PerCpuArray = PerCpuArray::with_max_entries(1, 0); #[xdp] pub fn net_guardia(ctx: XdpContext) -> u32 { - match unsafe { parsing(ctx) } { - Ok(ret) => ret, - Err(_) => xdp_action::XDP_PASS, - } + unsafe { packet_intake(ctx).unwrap_or(xdp_action::XDP_PASS) } } -unsafe fn parsing(ctx: XdpContext) -> Result { - unsafe { - let start = ctx.data(); - let end = ctx.data_end(); - let event = parsing::parse_packet(start, end)?; - let ptr = PARSED_PACKET.get_ptr_mut(0).ok_or(())?; - let parsed_packet = ptr.as_mut().ok_or(())?; - *parsed_packet = event; - if PROGRAM_ARRAY.tail_call(&ctx, 0).is_err() { - error!(&ctx, "Tail call failed"); - } - Err(()) +unsafe fn packet_intake(ctx: XdpContext) -> Result { + let start = ctx.data(); + let end = ctx.data_end(); + let ptr = PARSED_PACKET.get_ptr_mut(0).ok_or(())?; + parsing::parse_packet(start, end, ptr)?; + if unsafe { PROGRAM_ARRAY.tail_call(&ctx, 0).is_err() } { + error!(&ctx, "Tail call failed"); } + Ok(xdp_action::XDP_PASS) } #[xdp] pub fn statistics(ctx: XdpContext) -> u32 { - match unsafe { try_statistics(ctx) } { - Ok(ret) => ret, - Err(_) => xdp_action::XDP_PASS, + unsafe { + try_statistics(ctx).unwrap_or(xdp_action::XDP_PASS) } } unsafe fn try_statistics(_: XdpContext) -> Result { unsafe { let ptr = PARSED_PACKET.get_ptr(0).ok_or(())?; - let parsed_packet = ptr.read(); - match parsed_packet.eth_type { - EtherType::Ipv4 => { - let event = parsed_packet.into_ipv4_event(); - statistics::ipv4_update_stats(&event); + let parsed_packet = &*ptr; + match parsed_packet { + Event::IPv4(event) => { + statistics::ipv4_update_stats(event); } - EtherType::Ipv6 => { - let event = parsed_packet.into_ipv6_event(); - statistics::ipv6_update_stats(&event); + Event::IPv6(event) => { + statistics::ipv6_update_stats(event); } - _ => Err(())?, } Ok(xdp_action::XDP_PASS) } diff --git a/net-guardia-ingress-ebpf/src/action/service.rs b/net-guardia-ingress-ebpf/src/action/service.rs index e8293c6..307bde3 100644 --- a/net-guardia-ingress-ebpf/src/action/service.rs +++ b/net-guardia-ingress-ebpf/src/action/service.rs @@ -28,18 +28,18 @@ static IPV4_SSH_BLACK_LIST: HashMap = HashMap::with_max_entri #[map] static IPV6_SSH_BLACK_LIST: HashMap = HashMap::with_max_entries(MAX_RULES as u32, 0); -pub fn ipv4_service_rule_violation(start: usize, end: usize, event: IPv4Event) -> bool { +pub fn ipv4_service_rule_violation(start: usize, end: usize, event: &IPv4Event) -> bool { let protocol = event.protocol; - let source = event.get_source(); - let destination = event.get_destination(); + let source = event.source_addr(); + let destination = event.destination_addr(); ipv4_http_service_violation(start, end, &protocol, &destination) || ipv4_ssh_service_violation(&source, &destination) } -pub fn ipv6_service_rule_violation(start: usize, end: usize, event: IPv6Event) -> bool { +pub fn ipv6_service_rule_violation(start: usize, end: usize, event: &IPv6Event) -> bool { let protocol = event.protocol; - let source = event.get_source(); - let destination = event.get_destination(); + let source = event.source_addr(); + let destination = event.destination_addr(); ipv6_http_service_violation(start, end, &protocol, &destination) || ipv6_ssh_service_violation(&source, &destination) } diff --git a/net-guardia-ingress-ebpf/src/action/statistics.rs b/net-guardia-ingress-ebpf/src/action/statistics.rs index d7a3bf8..05c4ec6 100644 --- a/net-guardia-ingress-ebpf/src/action/statistics.rs +++ b/net-guardia-ingress-ebpf/src/action/statistics.rs @@ -1,4 +1,3 @@ -use aya_ebpf::helpers::bpf_ktime_get_ns; use aya_ebpf::macros::map; use aya_ebpf::maps::LruHashMap; use net_guardia_common::model::event::{IPv4Event, IPv6Event}; @@ -33,9 +32,8 @@ static IPV6_INGRESS_DST_1HOUR: LruHashMap = LruHashMap::w pub fn ipv4_update_stats(event: &IPv4Event) { unsafe { - let now = bpf_ktime_get_ns(); - let source = event.get_source(); - let destination = event.get_destination(); + let source = event.source_addr(); + let destination = event.destination_addr(); ipv4_update_flow_stats(&IPV4_INGRESS_SRC_1MIN, &source, event); ipv4_update_flow_stats(&IPV4_INGRESS_SRC_10MIN, &source, event); ipv4_update_flow_stats(&IPV4_INGRESS_SRC_1HOUR, &source, event); @@ -47,9 +45,8 @@ pub fn ipv4_update_stats(event: &IPv4Event) { pub fn ipv6_update_stats(event: &IPv6Event) { unsafe { - let now = bpf_ktime_get_ns(); - let source = event.get_source(); - let destination = event.get_destination(); + let source = event.source_addr(); + let destination = event.destination_addr(); ipv6_update_flow_status(&IPV6_INGRESS_SRC_1MIN, &source, event); ipv6_update_flow_status(&IPV6_INGRESS_SRC_10MIN, &source, event); ipv6_update_flow_status(&IPV6_INGRESS_SRC_1HOUR, &source, event); diff --git a/net-guardia-ingress-ebpf/src/action/transmission.rs b/net-guardia-ingress-ebpf/src/action/transmission.rs index a7b76ec..94931a6 100644 --- a/net-guardia-ingress-ebpf/src/action/transmission.rs +++ b/net-guardia-ingress-ebpf/src/action/transmission.rs @@ -1,21 +1,24 @@ -use aya_ebpf::macros::map; -use aya_ebpf::maps::RingBuf; -use net_guardia_common::define::other::STANDARD_MTU; -use net_guardia_common::define::setting::MAX_BUFFERED_PACKETS; -use net_guardia_common::model::event::Event; -use net_guardia_common::model::packet::Packet; +use aya_ebpf::{macros::map, maps::RingBuf}; +use net_guardia_common::{ + define::{other::STANDARD_MTU, setting::MAX_BUFFERED_PACKETS}, + model::{event::Event, packet::Packet}, +}; #[map] static PACKET_RING: RingBuf = RingBuf::with_byte_size((MAX_BUFFERED_PACKETS * STANDARD_MTU) as u32, 0); -pub fn transmission(start: usize, end: usize, event: Event) -> Result<(), ()> { - if end - start != STANDARD_MTU { +pub fn transmission(start: usize, end: usize, event: *mut Event) -> Result<(), ()> { + if start + STANDARD_MTU > end { return Err(()); } if let Some(mut entry) = PACKET_RING.reserve::(0) { unsafe { let packet_ptr = entry.as_mut_ptr(); - core::ptr::write(&mut (*packet_ptr).event, event); + core::ptr::copy_nonoverlapping( + event as *const u8, + &mut (*packet_ptr).event as *mut Event as *mut u8, + size_of::(), + ); core::ptr::copy_nonoverlapping(start as *const u8, (*packet_ptr).raw_data.as_mut_ptr(), STANDARD_MTU); } entry.submit(0); diff --git a/net-guardia-ingress-ebpf/src/main.rs b/net-guardia-ingress-ebpf/src/main.rs index 573bc0d..aafcef4 100644 --- a/net-guardia-ingress-ebpf/src/main.rs +++ b/net-guardia-ingress-ebpf/src/main.rs @@ -12,7 +12,6 @@ use aya_ebpf::{ use aya_log_ebpf::error; use net_guardia_common::ebpf::parsing; use net_guardia_common::model::event::Event; -use network_types::eth::EtherType; #[map] static PROGRAM_ARRAY: ProgramArray = ProgramArray::with_max_entries(8, 0); @@ -21,59 +20,51 @@ static PARSED_PACKET: PerCpuArray = PerCpuArray::with_max_entries(1, 0); #[xdp] pub fn net_guardia(ctx: XdpContext) -> u32 { - match unsafe { parsing(ctx) } { - Ok(ret) => ret, - Err(_) => xdp_action::XDP_PASS, + unsafe { + packet_intake(ctx).unwrap_or(xdp_action::XDP_PASS) } } -unsafe fn parsing(ctx: XdpContext) -> Result { - unsafe { - let start = ctx.data(); - let end = ctx.data_end(); - let event = parsing::parse_packet(start, end)?; - let ptr = PARSED_PACKET.get_ptr_mut(0).ok_or(())?; - let parsed_packet = ptr.as_mut().ok_or(())?; - *parsed_packet = event; - if PROGRAM_ARRAY.tail_call(&ctx, 0).is_err() { - error!(&ctx, "Tail call failed"); - } - Err(()) +unsafe fn packet_intake(ctx: XdpContext) -> Result { + let start = ctx.data(); + let end = ctx.data_end(); + let ptr = PARSED_PACKET.get_ptr_mut(0).ok_or(())?; + parsing::parse_packet(start, end, ptr)?; + transmission::transmission(start, end, ptr)?; + if unsafe { PROGRAM_ARRAY.tail_call(&ctx, 0).is_err() } { + error!(&ctx, "Tail call failed"); } + Ok(xdp_action::XDP_PASS) } #[xdp] pub fn access_control(ctx: XdpContext) -> u32 { - match unsafe { try_access_control(ctx) } { - Ok(ret) => ret, - Err(_) => xdp_action::XDP_PASS, + unsafe { + try_access_control(ctx).unwrap_or(xdp_action::XDP_PASS) } } unsafe fn try_access_control(ctx: XdpContext) -> Result { unsafe { let ptr = PARSED_PACKET.get_ptr(0).ok_or(())?; - let parsed_packet = ptr.read(); - match parsed_packet.eth_type { - EtherType::Ipv4 => { - let event = parsed_packet.into_ipv4_event(); - if access_control::ipv4_is_whitelisted(&event) { + let parsed_packet = &*ptr; + match parsed_packet { + Event::IPv4(event) => { + if access_control::ipv4_is_whitelisted(event) { return Ok(xdp_action::XDP_PASS); } - if access_control::ipv4_is_blacklisted(&event) { + if access_control::ipv4_is_blacklisted(event) { return Ok(xdp_action::XDP_DROP); } } - EtherType::Ipv6 => { - let event = parsed_packet.into_ipv6_event(); - if access_control::ipv6_is_whitelisted(&event) { + Event::IPv6(event) => { + if access_control::ipv6_is_whitelisted(event) { return Ok(xdp_action::XDP_PASS); } - if access_control::ipv6_is_blacklisted(&event) { + if access_control::ipv6_is_blacklisted(event) { return Ok(xdp_action::XDP_DROP); } } - _ => Err(())?, } if PROGRAM_ARRAY.tail_call(&ctx, 1).is_err() { error!(&ctx, "Tail call failed"); @@ -84,9 +75,8 @@ unsafe fn try_access_control(ctx: XdpContext) -> Result { #[xdp] pub fn service(ctx: XdpContext) -> u32 { - match unsafe { try_service(ctx) } { - Ok(ret) => ret, - Err(_) => xdp_action::XDP_PASS, + unsafe { + try_service(ctx).unwrap_or(xdp_action::XDP_PASS) } } @@ -95,21 +85,18 @@ unsafe fn try_service(ctx: XdpContext) -> Result { let start = ctx.data(); let end = ctx.data_end(); let ptr = PARSED_PACKET.get_ptr(0).ok_or(())?; - let parsed_packet = ptr.read(); - match parsed_packet.eth_type { - EtherType::Ipv4 => { - let event = parsed_packet.into_ipv4_event(); + let parsed_packet = &*ptr; + match parsed_packet { + Event::IPv4(event) => { if service::ipv4_service_rule_violation(start, end, event) { return Ok(xdp_action::XDP_DROP); } } - EtherType::Ipv6 => { - let event = parsed_packet.into_ipv6_event(); + Event::IPv6(event) => { if service::ipv6_service_rule_violation(start, end, event) { return Ok(xdp_action::XDP_DROP); } } - _ => Err(())?, } if PROGRAM_ARRAY.tail_call(&ctx, 2).is_err() { error!(&ctx, "Tail call failed"); @@ -118,48 +105,24 @@ unsafe fn try_service(ctx: XdpContext) -> Result { } } -#[xdp] -pub fn transmission(ctx: XdpContext) -> u32 { - match unsafe { try_transmission(ctx) } { - Ok(ret) => ret, - Err(_) => xdp_action::XDP_PASS, - } -} - -unsafe fn try_transmission(ctx: XdpContext) -> Result { - let start = ctx.data(); - let end = ctx.data_end(); - let ptr = PARSED_PACKET.get_ptr(0).ok_or(())?; - let parsed_packet = ptr.read(); - transmission::transmission(start, end, parsed_packet)?; - if unsafe { PROGRAM_ARRAY.tail_call(&ctx, 3).is_err() } { - error!(&ctx, "Tail call failed"); - } - Err(()) -} - #[xdp] pub fn statistics(ctx: XdpContext) -> u32 { - match unsafe { try_statistics(ctx) } { - Ok(ret) => ret, - Err(_) => xdp_action::XDP_PASS, + unsafe { + try_statistics(ctx).unwrap_or(xdp_action::XDP_PASS) } } unsafe fn try_statistics(_: XdpContext) -> Result { unsafe { let ptr = PARSED_PACKET.get_ptr(0).ok_or(())?; - let parsed_packet = ptr.read(); - match parsed_packet.eth_type { - EtherType::Ipv4 => { - let event = parsed_packet.into_ipv4_event(); + let parsed_packet = &*ptr; + match parsed_packet { + Event::IPv4(event) => { statistics::ipv4_update_stats(&event); } - EtherType::Ipv6 => { - let event = parsed_packet.into_ipv6_event(); + Event::IPv6(event) => { statistics::ipv6_update_stats(&event); } - _ => Err(())?, } Ok(xdp_action::XDP_PASS) } diff --git a/net-guardia/src/core/system.rs b/net-guardia/src/core/system.rs index 3bb30b0..dfd506d 100644 --- a/net-guardia/src/core/system.rs +++ b/net-guardia/src/core/system.rs @@ -91,8 +91,7 @@ impl System { 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 ingress_ebpf, &mut ingress_program_array, "transmission", 3)?; - Self::load_program(&mut ingress_ebpf, &mut ingress_program_array, "statistics", 4)?; + Self::load_program(&mut ingress_ebpf, &mut ingress_program_array, "statistics", 2)?; Ok((ingress_ebpf, ingress_program_array)) }