Skip to content

Commit

Permalink
epbf: send the whole packet header
Browse files Browse the repository at this point in the history
  • Loading branch information
pythops committed Sep 11, 2024
1 parent 30a332d commit 2d61340
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 134 deletions.
6 changes: 4 additions & 2 deletions oryx-ebpf/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion oryx-ebpf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ homepage = "https://github.com/pythops/oryx"
aya-ebpf = "0.1.0"
aya-log-ebpf = "0.1.0"
oryx-common = { path = "../oryx-common" }
network-types = "0.0.6"
network-types = { git = "https://github.com/vadorovsky/network-types.git", rev = "e0ee8d5" }

[[bin]]
name = "oryx"
Expand Down
155 changes: 24 additions & 131 deletions oryx-ebpf/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
#![no_std]
#![no_main]

use core::mem;
use core::net::IpAddr;

use aya_ebpf::{
bindings::TC_ACT_PIPE,
macros::{classifier, map},
Expand All @@ -12,14 +9,11 @@ use aya_ebpf::{
};

use network_types::{
arp::ArpHdr,
eth::{EthHdr, EtherType},
icmp::IcmpHdr,
ip::{IpProto, Ipv4Hdr, Ipv6Hdr},
tcp::TcpHdr,
udp::UdpHdr,
ip::{IpHdr, IpProto, Ipv4Hdr, Ipv6Hdr},
};

use oryx_common::{IcmpPacket, IcmpType, IpPacket, TcpPacket, UdpPacket};
use oryx_common::RawPacket;

#[map]
static DATA: RingBuf = RingBuf::with_byte_size(4096 * 40, 0);
Expand All @@ -33,125 +27,8 @@ pub fn oryx(ctx: TcContext) -> i32 {
}

#[inline]
fn ptr_at<T>(ctx: &TcContext, offset: usize) -> Result<*const T, ()> {
let start = ctx.data();
let end = ctx.data_end();
let len = mem::size_of::<T>();

if start + offset + len > end {
return Err(());
}

Ok((start + offset) as *const T)
}

#[inline]
fn parse_ipv4_packet(ctx: &TcContext) -> Result<IpPacket, ()> {
let header: Ipv4Hdr = ctx.load(EthHdr::LEN).map_err(|_| ())?;

let dst_ip: IpAddr = header.dst_addr().into();

let src_ip: IpAddr = header.src_addr().into();

match header.proto {
IpProto::Tcp => {
let tcphdr: *const TcpHdr = ptr_at(ctx, EthHdr::LEN + Ipv4Hdr::LEN)?;
let src_port = u16::from_be(unsafe { (*tcphdr).source });
let dst_port = u16::from_be(unsafe { (*tcphdr).dest });

let packet = TcpPacket {
src_ip,
dst_ip,
src_port,
dst_port,
};

Ok(IpPacket::Tcp(packet))
}
IpProto::Udp => {
let udphdr: *const UdpHdr = ptr_at(ctx, EthHdr::LEN + Ipv4Hdr::LEN)?;
let src_port = u16::from_be(unsafe { (*udphdr).source });
let dst_port = u16::from_be(unsafe { (*udphdr).dest });
let packet = UdpPacket {
src_ip,
dst_ip,
src_port,
dst_port,
};

Ok(IpPacket::Udp(packet))
}
IpProto::Icmp => {
let icmp_header: *const IcmpHdr = ptr_at(ctx, EthHdr::LEN + Ipv4Hdr::LEN)?;
let icmp_type = u8::from_be(unsafe { (*icmp_header).type_ });
let icmp_type = match icmp_type {
0 => IcmpType::EchoReply,
3 => IcmpType::DestinationUnreachable,
8 => IcmpType::EchoRequest,
_ => return Err(()),
};

let packet = IcmpPacket {
src_ip,
dst_ip,
icmp_type,
};
Ok(IpPacket::Icmp(packet))
}
_ => Err(()),
}
}

#[inline]
fn parse_ipv6_packet(ctx: &TcContext) -> Result<IpPacket, ()> {
let header: Ipv6Hdr = ctx.load(EthHdr::LEN).map_err(|_| ())?;

let dst_ip: IpAddr = header.dst_addr().into();
let src_ip: IpAddr = header.src_addr().into();

match header.next_hdr {
IpProto::Tcp => {
let tcphdr: *const TcpHdr = ptr_at(ctx, EthHdr::LEN + Ipv6Hdr::LEN)?;
Ok(IpPacket::Tcp(TcpPacket {
src_ip,
dst_ip,
src_port: u16::from_be(unsafe { (*tcphdr).source }),
dst_port: u16::from_be(unsafe { (*tcphdr).dest }),
}))
}

IpProto::Udp => {
let udphdr: *const UdpHdr = ptr_at(ctx, EthHdr::LEN + Ipv6Hdr::LEN)?;
Ok(IpPacket::Udp(UdpPacket {
src_ip,
dst_ip,
src_port: u16::from_be(unsafe { (*udphdr).source }),
dst_port: u16::from_be(unsafe { (*udphdr).source }),
}))
}

IpProto::Ipv6Icmp => {
let icmp_header: *const IcmpHdr = ptr_at(ctx, EthHdr::LEN + Ipv6Hdr::LEN)?;
let icmp_type = match u8::from_be(unsafe { (*icmp_header).type_ }) {
129 => IcmpType::EchoReply,
1 => IcmpType::DestinationUnreachable,
128 => IcmpType::EchoRequest,
_ => return Err(()),
};

Ok(IpPacket::Icmp(IcmpPacket {
src_ip,
dst_ip,
icmp_type,
}))
}
_ => Err(()),
}
}

#[inline]
fn submit(packet: IpPacket) {
if let Some(mut buf) = DATA.reserve::<IpPacket>(0) {
fn submit(packet: RawPacket) {
if let Some(mut buf) = DATA.reserve::<RawPacket>(0) {
unsafe { (*buf.as_mut_ptr()) = packet };
buf.submit(0);
}
Expand All @@ -163,12 +40,28 @@ fn process(ctx: TcContext) -> Result<i32, ()> {

match ethhdr.ether_type {
EtherType::Ipv4 => {
submit(parse_ipv4_packet(&ctx)?);
let header: Ipv4Hdr = ctx.load(EthHdr::LEN).map_err(|_| ())?;
match header.proto {
IpProto::Tcp | IpProto::Udp | IpProto::Icmp => {
submit(RawPacket::Ip(IpHdr::V4(header)));
}
_ => {}
}
}
EtherType::Ipv6 => {
submit(parse_ipv6_packet(&ctx)?);
let header: Ipv6Hdr = ctx.load(EthHdr::LEN).map_err(|_| ())?;
match header.next_hdr {
IpProto::Tcp | IpProto::Udp | IpProto::Icmp => {
submit(RawPacket::Ip(IpHdr::V6(header)));
}
_ => {}
}
}
EtherType::Arp => {
let header: ArpHdr = ctx.load(EthHdr::LEN).map_err(|_| ())?;
submit(RawPacket::Arp(header));
}
_ => return Ok(TC_ACT_PIPE),
_ => {}
};

Ok(TC_ACT_PIPE)
Expand Down

0 comments on commit 2d61340

Please sign in to comment.