refactor: Refactor packet parsing and event handling for better speed (#5)

This commit is contained in:
DaLaw2 2025-08-31 13:18:26 +08:00 committed by GitHub
parent 187eb8a8ac
commit 926d100d17
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 179 additions and 270 deletions

View File

@ -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<Event, ()> {
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<Event, ()> {
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<Event, ()> {
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<Event, ()> {
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(())
}
}

View File

@ -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,

View File

@ -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],
}

View File

@ -32,8 +32,8 @@ static IPV6_INGRESS_DST_1HOUR: LruHashMap<AddrPortV6, FlowStats> = 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);

View File

@ -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<Event> = 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<u32, ()> {
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<u32, ()> {
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<u32, ()> {
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)
}

View File

@ -28,18 +28,18 @@ static IPV4_SSH_BLACK_LIST: HashMap<IPv4, PlaceHolder> = HashMap::with_max_entri
#[map]
static IPV6_SSH_BLACK_LIST: HashMap<IPv6, PlaceHolder> = 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)
}

View File

@ -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<AddrPortV6, FlowStats> = 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);

View File

@ -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::<Packet>(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::<Event>(),
);
core::ptr::copy_nonoverlapping(start as *const u8, (*packet_ptr).raw_data.as_mut_ptr(), STANDARD_MTU);
}
entry.submit(0);

View File

@ -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<Event> = 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<u32, ()> {
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<u32, ()> {
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<u32, ()> {
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<u32, ()> {
#[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<u32, ()> {
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<u32, ()> {
}
}
#[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<u32, ()> {
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<u32, ()> {
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)
}

View File

@ -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))
}