From dc1a0703bc0c694787e46c5a326ab7da55077aaa Mon Sep 17 00:00:00 2001 From: Mahesh Rayas Date: Fri, 1 Dec 2023 10:07:33 +1100 Subject: [PATCH] feat: Replace network header types from bindings.rs to crate (#147) fixes: https://github.com/kubernetes-sigs/blixt/issues/99 --- dataplane/ebpf/Cargo.toml | 3 +- dataplane/ebpf/src/bindings.rs | 364 ------------------------------ dataplane/ebpf/src/egress/icmp.rs | 26 +-- dataplane/ebpf/src/egress/tcp.rs | 20 +- dataplane/ebpf/src/ingress/tcp.rs | 20 +- dataplane/ebpf/src/ingress/udp.rs | 22 +- dataplane/ebpf/src/main.rs | 67 +++--- dataplane/ebpf/src/utils.rs | 17 -- dataplane/xtask/src/codegen.rs | 22 -- dataplane/xtask/src/main.rs | 3 - 10 files changed, 75 insertions(+), 489 deletions(-) delete mode 100644 dataplane/ebpf/src/bindings.rs delete mode 100644 dataplane/xtask/src/codegen.rs diff --git a/dataplane/ebpf/Cargo.toml b/dataplane/ebpf/Cargo.toml index e162a6cd..56fb245a 100644 --- a/dataplane/ebpf/Cargo.toml +++ b/dataplane/ebpf/Cargo.toml @@ -8,7 +8,8 @@ publish = false aya-bpf = { git = "https://github.com/aya-rs/aya", branch = "main" } aya-log-ebpf = { git = "https://github.com/aya-rs/aya", branch = "main" } common = { path = "../common" } -memoffset = "0.8" +memoffset = "0.9" +network-types = "0.0.5" [[bin]] name = "loader" diff --git a/dataplane/ebpf/src/bindings.rs b/dataplane/ebpf/src/bindings.rs deleted file mode 100644 index 333b1dcc..00000000 --- a/dataplane/ebpf/src/bindings.rs +++ /dev/null @@ -1,364 +0,0 @@ -/* automatically generated by rust-bindgen 0.64.0 */ - -#[repr(C)] -#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct __BindgenBitfieldUnit { - storage: Storage, -} -impl __BindgenBitfieldUnit { - #[inline] - pub const fn new(storage: Storage) -> Self { - Self { storage } - } -} -impl __BindgenBitfieldUnit -where - Storage: AsRef<[u8]> + AsMut<[u8]>, -{ - #[inline] - pub fn get_bit(&self, index: usize) -> bool { - debug_assert!(index / 8 < self.storage.as_ref().len()); - let byte_index = index / 8; - let byte = self.storage.as_ref()[byte_index]; - let bit_index = if cfg!(target_endian = "big") { - 7 - (index % 8) - } else { - index % 8 - }; - let mask = 1 << bit_index; - byte & mask == mask - } - #[inline] - pub fn set_bit(&mut self, index: usize, val: bool) { - debug_assert!(index / 8 < self.storage.as_ref().len()); - let byte_index = index / 8; - let byte = &mut self.storage.as_mut()[byte_index]; - let bit_index = if cfg!(target_endian = "big") { - 7 - (index % 8) - } else { - index % 8 - }; - let mask = 1 << bit_index; - if val { - *byte |= mask; - } else { - *byte &= !mask; - } - } - #[inline] - pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - let mut val = 0; - for i in 0..(bit_width as usize) { - if self.get_bit(i + bit_offset) { - let index = if cfg!(target_endian = "big") { - bit_width as usize - 1 - i - } else { - i - }; - val |= 1 << index; - } - } - val - } - #[inline] - pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) { - debug_assert!(bit_width <= 64); - debug_assert!(bit_offset / 8 < self.storage.as_ref().len()); - debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len()); - for i in 0..(bit_width as usize) { - let mask = 1 << i; - let val_bit_is_set = val & mask == mask; - let index = if cfg!(target_endian = "big") { - bit_width as usize - 1 - i - } else { - i - }; - self.set_bit(index + bit_offset, val_bit_is_set); - } - } -} -pub type __u8 = ::aya_bpf::cty::c_uchar; -pub type __u16 = ::aya_bpf::cty::c_ushort; -pub type __u32 = ::aya_bpf::cty::c_uint; -pub type __be16 = __u16; -pub type __be32 = __u32; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct ethhdr { - pub h_dest: [::aya_bpf::cty::c_uchar; 6usize], - pub h_source: [::aya_bpf::cty::c_uchar; 6usize], - pub h_proto: __be16, -} -pub type __sum16 = __u16; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct iphdr { - pub _bitfield_align_1: [u8; 0], - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 1usize]>, - pub tos: __u8, - pub tot_len: __be16, - pub id: __be16, - pub frag_off: __be16, - pub ttl: __u8, - pub protocol: __u8, - pub check: __sum16, - pub saddr: __be32, - pub daddr: __be32, -} -impl iphdr { - #[inline] - pub fn ihl(&self) -> __u8 { - unsafe { ::core::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u8) } - } - #[inline] - pub fn set_ihl(&mut self, val: __u8) { - unsafe { - let val: u8 = ::core::mem::transmute(val); - self._bitfield_1.set(0usize, 4u8, val as u64) - } - } - #[inline] - pub fn version(&self) -> __u8 { - unsafe { ::core::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u8) } - } - #[inline] - pub fn set_version(&mut self, val: __u8) { - unsafe { - let val: u8 = ::core::mem::transmute(val); - self._bitfield_1.set(4usize, 4u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1(ihl: __u8, version: __u8) -> __BindgenBitfieldUnit<[u8; 1usize]> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 1usize]> = Default::default(); - __bindgen_bitfield_unit.set(0usize, 4u8, { - let ihl: u8 = unsafe { ::core::mem::transmute(ihl) }; - ihl as u64 - }); - __bindgen_bitfield_unit.set(4usize, 4u8, { - let version: u8 = unsafe { ::core::mem::transmute(version) }; - version as u64 - }); - __bindgen_bitfield_unit - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct tcphdr { - pub source: __be16, - pub dest: __be16, - pub seq: __be32, - pub ack_seq: __be32, - pub _bitfield_align_1: [u8; 0], - pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize]>, - pub window: __be16, - pub check: __sum16, - pub urg_ptr: __be16, -} -impl tcphdr { - #[inline] - pub fn res1(&self) -> __u16 { - unsafe { ::core::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u16) } - } - #[inline] - pub fn set_res1(&mut self, val: __u16) { - unsafe { - let val: u16 = ::core::mem::transmute(val); - self._bitfield_1.set(0usize, 4u8, val as u64) - } - } - #[inline] - pub fn doff(&self) -> __u16 { - unsafe { ::core::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u16) } - } - #[inline] - pub fn set_doff(&mut self, val: __u16) { - unsafe { - let val: u16 = ::core::mem::transmute(val); - self._bitfield_1.set(4usize, 4u8, val as u64) - } - } - #[inline] - pub fn fin(&self) -> __u16 { - unsafe { ::core::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u16) } - } - #[inline] - pub fn set_fin(&mut self, val: __u16) { - unsafe { - let val: u16 = ::core::mem::transmute(val); - self._bitfield_1.set(8usize, 1u8, val as u64) - } - } - #[inline] - pub fn syn(&self) -> __u16 { - unsafe { ::core::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u16) } - } - #[inline] - pub fn set_syn(&mut self, val: __u16) { - unsafe { - let val: u16 = ::core::mem::transmute(val); - self._bitfield_1.set(9usize, 1u8, val as u64) - } - } - #[inline] - pub fn rst(&self) -> __u16 { - unsafe { ::core::mem::transmute(self._bitfield_1.get(10usize, 1u8) as u16) } - } - #[inline] - pub fn set_rst(&mut self, val: __u16) { - unsafe { - let val: u16 = ::core::mem::transmute(val); - self._bitfield_1.set(10usize, 1u8, val as u64) - } - } - #[inline] - pub fn psh(&self) -> __u16 { - unsafe { ::core::mem::transmute(self._bitfield_1.get(11usize, 1u8) as u16) } - } - #[inline] - pub fn set_psh(&mut self, val: __u16) { - unsafe { - let val: u16 = ::core::mem::transmute(val); - self._bitfield_1.set(11usize, 1u8, val as u64) - } - } - #[inline] - pub fn ack(&self) -> __u16 { - unsafe { ::core::mem::transmute(self._bitfield_1.get(12usize, 1u8) as u16) } - } - #[inline] - pub fn set_ack(&mut self, val: __u16) { - unsafe { - let val: u16 = ::core::mem::transmute(val); - self._bitfield_1.set(12usize, 1u8, val as u64) - } - } - #[inline] - pub fn urg(&self) -> __u16 { - unsafe { ::core::mem::transmute(self._bitfield_1.get(13usize, 1u8) as u16) } - } - #[inline] - pub fn set_urg(&mut self, val: __u16) { - unsafe { - let val: u16 = ::core::mem::transmute(val); - self._bitfield_1.set(13usize, 1u8, val as u64) - } - } - #[inline] - pub fn ece(&self) -> __u16 { - unsafe { ::core::mem::transmute(self._bitfield_1.get(14usize, 1u8) as u16) } - } - #[inline] - pub fn set_ece(&mut self, val: __u16) { - unsafe { - let val: u16 = ::core::mem::transmute(val); - self._bitfield_1.set(14usize, 1u8, val as u64) - } - } - #[inline] - pub fn cwr(&self) -> __u16 { - unsafe { ::core::mem::transmute(self._bitfield_1.get(15usize, 1u8) as u16) } - } - #[inline] - pub fn set_cwr(&mut self, val: __u16) { - unsafe { - let val: u16 = ::core::mem::transmute(val); - self._bitfield_1.set(15usize, 1u8, val as u64) - } - } - #[inline] - pub fn new_bitfield_1( - res1: __u16, - doff: __u16, - fin: __u16, - syn: __u16, - rst: __u16, - psh: __u16, - ack: __u16, - urg: __u16, - ece: __u16, - cwr: __u16, - ) -> __BindgenBitfieldUnit<[u8; 2usize]> { - let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize]> = Default::default(); - __bindgen_bitfield_unit.set(0usize, 4u8, { - let res1: u16 = unsafe { ::core::mem::transmute(res1) }; - res1 as u64 - }); - __bindgen_bitfield_unit.set(4usize, 4u8, { - let doff: u16 = unsafe { ::core::mem::transmute(doff) }; - doff as u64 - }); - __bindgen_bitfield_unit.set(8usize, 1u8, { - let fin: u16 = unsafe { ::core::mem::transmute(fin) }; - fin as u64 - }); - __bindgen_bitfield_unit.set(9usize, 1u8, { - let syn: u16 = unsafe { ::core::mem::transmute(syn) }; - syn as u64 - }); - __bindgen_bitfield_unit.set(10usize, 1u8, { - let rst: u16 = unsafe { ::core::mem::transmute(rst) }; - rst as u64 - }); - __bindgen_bitfield_unit.set(11usize, 1u8, { - let psh: u16 = unsafe { ::core::mem::transmute(psh) }; - psh as u64 - }); - __bindgen_bitfield_unit.set(12usize, 1u8, { - let ack: u16 = unsafe { ::core::mem::transmute(ack) }; - ack as u64 - }); - __bindgen_bitfield_unit.set(13usize, 1u8, { - let urg: u16 = unsafe { ::core::mem::transmute(urg) }; - urg as u64 - }); - __bindgen_bitfield_unit.set(14usize, 1u8, { - let ece: u16 = unsafe { ::core::mem::transmute(ece) }; - ece as u64 - }); - __bindgen_bitfield_unit.set(15usize, 1u8, { - let cwr: u16 = unsafe { ::core::mem::transmute(cwr) }; - cwr as u64 - }); - __bindgen_bitfield_unit - } -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct udphdr { - pub source: __be16, - pub dest: __be16, - pub len: __be16, - pub check: __sum16, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct icmphdr { - pub type_: __u8, - pub code: __u8, - pub checksum: __sum16, - pub un: icmphdr__bindgen_ty_1, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union icmphdr__bindgen_ty_1 { - pub echo: icmphdr__bindgen_ty_1__bindgen_ty_1, - pub gateway: __be32, - pub frag: icmphdr__bindgen_ty_1__bindgen_ty_2, - pub reserved: [__u8; 4usize], -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct icmphdr__bindgen_ty_1__bindgen_ty_1 { - pub id: __be16, - pub sequence: __be16, -} -#[repr(C)] -#[derive(Copy, Clone)] -pub struct icmphdr__bindgen_ty_1__bindgen_ty_2 { - pub __unused: __be16, - pub mtu: __be16, -} diff --git a/dataplane/ebpf/src/egress/icmp.rs b/dataplane/ebpf/src/egress/icmp.rs index 16e31754..f666d361 100644 --- a/dataplane/ebpf/src/egress/icmp.rs +++ b/dataplane/ebpf/src/egress/icmp.rs @@ -8,22 +8,21 @@ use core::mem; use aya_bpf::{bindings::TC_ACT_PIPE, helpers::bpf_csum_diff, programs::TcContext}; use aya_log_ebpf::info; +use network_types::{eth::EthHdr, icmp::IcmpHdr, ip::Ipv4Hdr}; use crate::{ - bindings::{icmphdr, iphdr}, - utils::{csum_fold_helper, ptr_at, ETH_HDR_LEN, IP_HDR_LEN}, + utils::{csum_fold_helper, ptr_at}, BLIXT_CONNTRACK, }; -const ICMP_HDR_LEN: usize = mem::size_of::(); const ICMP_PROTO_TYPE_UNREACH: u8 = 3; pub fn handle_icmp_egress(ctx: TcContext) -> Result { - let ip_hdr: *mut iphdr = unsafe { ptr_at(&ctx, ETH_HDR_LEN) }?; + let ip_hdr: *mut Ipv4Hdr = unsafe { ptr_at(&ctx, EthHdr::LEN)? }; - let icmp_header_offset = ETH_HDR_LEN + IP_HDR_LEN; + let icmp_header_offset = EthHdr::LEN + Ipv4Hdr::LEN; - let icmp_hdr: *mut icmphdr = unsafe { ptr_at(&ctx, icmp_header_offset)? }; + let icmp_hdr: *mut IcmpHdr = unsafe { ptr_at(&ctx, icmp_header_offset)? }; // We only care about redirecting port unreachable messages currently so a // UDP client can tell when the server is shutdown @@ -31,19 +30,19 @@ pub fn handle_icmp_egress(ctx: TcContext) -> Result { return Ok(TC_ACT_PIPE); } - let dest_addr = unsafe { (*ip_hdr).daddr }; + let dest_addr = unsafe { (*ip_hdr).dst_addr }; let new_src = unsafe { BLIXT_CONNTRACK.get(&dest_addr) }.ok_or(TC_ACT_PIPE)?; info!( &ctx, "Received a ICMP Unreachable packet destined for svc ip: {:i} ", - u32::from_be(unsafe { (*ip_hdr).daddr }) + u32::from_be(unsafe { (*ip_hdr).dst_addr }) ); // redirect icmp unreachable message back to client unsafe { - (*ip_hdr).saddr = new_src.0; + (*ip_hdr).src_addr = new_src.0; (*ip_hdr).check = 0; } @@ -52,17 +51,18 @@ pub fn handle_icmp_egress(ctx: TcContext) -> Result { mem::MaybeUninit::zeroed().assume_init(), 0, ip_hdr as *mut u32, - mem::size_of::() as u32, + Ipv4Hdr::LEN as u32, 0, ) } as u64; unsafe { (*ip_hdr).check = csum_fold_helper(full_cksum) }; // Get inner ipheader since we need to update that as well - let icmp_inner_ip_hdr: *mut iphdr = unsafe { ptr_at(&ctx, icmp_header_offset + ICMP_HDR_LEN) }?; + let icmp_inner_ip_hdr: *mut Ipv4Hdr = + unsafe { ptr_at(&ctx, icmp_header_offset + IcmpHdr::LEN) }?; unsafe { - (*icmp_inner_ip_hdr).daddr = new_src.0; + (*icmp_inner_ip_hdr).dst_addr = new_src.0; (*icmp_inner_ip_hdr).check = 0; } @@ -71,7 +71,7 @@ pub fn handle_icmp_egress(ctx: TcContext) -> Result { mem::MaybeUninit::zeroed().assume_init(), 0, icmp_inner_ip_hdr as *mut u32, - mem::size_of::() as u32, + Ipv4Hdr::LEN as u32, 0, ) } as u64; diff --git a/dataplane/ebpf/src/egress/tcp.rs b/dataplane/ebpf/src/egress/tcp.rs index 34d4f34e..89829329 100644 --- a/dataplane/ebpf/src/egress/tcp.rs +++ b/dataplane/ebpf/src/egress/tcp.rs @@ -12,21 +12,23 @@ use aya_bpf::{ programs::TcContext, }; use aya_log_ebpf::info; +use network_types::{eth::EthHdr, ip::Ipv4Hdr, tcp::TcpHdr}; use crate::{ - bindings::{iphdr, tcphdr}, - utils::{csum_fold_helper, ptr_at, ETH_HDR_LEN, IP_HDR_LEN}, + utils::{csum_fold_helper, ptr_at}, BLIXT_CONNTRACK, }; pub fn handle_tcp_egress(ctx: TcContext) -> Result { // gather the TCP header - let ip_hdr: *mut iphdr = unsafe { ptr_at(&ctx, ETH_HDR_LEN) }?; - let tcp_header_offset = ETH_HDR_LEN + IP_HDR_LEN; - let tcp_hdr: *mut tcphdr = unsafe { ptr_at(&ctx, tcp_header_offset)? }; + let ip_hdr: *mut Ipv4Hdr = unsafe { ptr_at(&ctx, EthHdr::LEN)? }; + + let tcp_header_offset = EthHdr::LEN + Ipv4Hdr::LEN; + + let tcp_hdr: *mut TcpHdr = unsafe { ptr_at(&ctx, tcp_header_offset)? }; // capture some IP and port information - let client_addr = unsafe { (*ip_hdr).daddr }; + let client_addr = unsafe { (*ip_hdr).dst_addr }; let dest_port = unsafe { (*tcp_hdr).dest.to_be() }; let ip_port_tuple = unsafe { BLIXT_CONNTRACK.get(&client_addr) }.ok_or(TC_ACT_PIPE)?; @@ -44,10 +46,10 @@ pub fn handle_tcp_egress(ctx: TcContext) -> Result { ); unsafe { - (*ip_hdr).saddr = ip_port_tuple.0; + (*ip_hdr).src_addr = ip_port_tuple.0; }; - if (ctx.data() + ETH_HDR_LEN + mem::size_of::()) > ctx.data_end() { + if (ctx.data() + EthHdr::LEN + Ipv4Hdr::LEN) > ctx.data_end() { info!(&ctx, "Iphdr is out of bounds"); return Ok(TC_ACT_OK); } @@ -58,7 +60,7 @@ pub fn handle_tcp_egress(ctx: TcContext) -> Result { mem::MaybeUninit::zeroed().assume_init(), 0, ip_hdr as *mut u32, - mem::size_of::() as u32, + Ipv4Hdr::LEN as u32, 0, ) } as u64; diff --git a/dataplane/ebpf/src/ingress/tcp.rs b/dataplane/ebpf/src/ingress/tcp.rs index 638faaa0..3fb56c5b 100644 --- a/dataplane/ebpf/src/ingress/tcp.rs +++ b/dataplane/ebpf/src/ingress/tcp.rs @@ -12,22 +12,22 @@ use aya_bpf::{ programs::TcContext, }; use aya_log_ebpf::info; +use network_types::{eth::EthHdr, ip::Ipv4Hdr, tcp::TcpHdr}; use crate::{ - bindings::{iphdr, tcphdr}, - utils::{csum_fold_helper, ptr_at, ETH_HDR_LEN, IP_HDR_LEN}, + utils::{csum_fold_helper, ptr_at}, BACKENDS, BLIXT_CONNTRACK, }; use common::BackendKey; pub fn handle_tcp_ingress(ctx: TcContext) -> Result { - let ip_hdr: *mut iphdr = unsafe { ptr_at(&ctx, ETH_HDR_LEN) }?; + let ip_hdr: *mut Ipv4Hdr = unsafe { ptr_at(&ctx, EthHdr::LEN)? }; - let tcp_header_offset = ETH_HDR_LEN + IP_HDR_LEN; + let tcp_header_offset = EthHdr::LEN + Ipv4Hdr::LEN; - let tcp_hdr: *mut tcphdr = unsafe { ptr_at(&ctx, tcp_header_offset)? }; + let tcp_hdr: *mut TcpHdr = unsafe { ptr_at(&ctx, tcp_header_offset) }?; - let original_daddr = unsafe { (*ip_hdr).daddr }; + let original_daddr = unsafe { (*ip_hdr).dst_addr }; let key = BackendKey { ip: u32::from_be(original_daddr), @@ -46,10 +46,10 @@ pub fn handle_tcp_ingress(ctx: TcContext) -> Result { ); unsafe { - (*ip_hdr).daddr = backend.daddr.to_be(); + (*ip_hdr).dst_addr = backend.daddr.to_be(); } - if (ctx.data() + ETH_HDR_LEN + mem::size_of::()) > ctx.data_end() { + if (ctx.data() + EthHdr::LEN + Ipv4Hdr::LEN) > ctx.data_end() { info!(&ctx, "Iphdr is out of bounds"); return Ok(TC_ACT_OK); } @@ -62,7 +62,7 @@ pub fn handle_tcp_ingress(ctx: TcContext) -> Result { mem::MaybeUninit::zeroed().assume_init(), 0, ip_hdr as *mut u32, - mem::size_of::() as u32, + Ipv4Hdr::LEN as u32, 0, ) } as u64; @@ -84,7 +84,7 @@ pub fn handle_tcp_ingress(ctx: TcContext) -> Result { unsafe { BLIXT_CONNTRACK.insert( - &(*ip_hdr).saddr, + &(*ip_hdr).src_addr, &(original_daddr, (*tcp_hdr).source.to_be() as u32), 0 as u64, )?; diff --git a/dataplane/ebpf/src/ingress/udp.rs b/dataplane/ebpf/src/ingress/udp.rs index 47c47f2e..1104f0d0 100644 --- a/dataplane/ebpf/src/ingress/udp.rs +++ b/dataplane/ebpf/src/ingress/udp.rs @@ -12,22 +12,22 @@ use aya_bpf::{ programs::TcContext, }; use aya_log_ebpf::{debug, info}; +use network_types::{eth::EthHdr, ip::Ipv4Hdr, udp::UdpHdr}; use crate::{ - bindings::{iphdr, udphdr}, - utils::{csum_fold_helper, ptr_at, ETH_HDR_LEN, IP_HDR_LEN}, + utils::{csum_fold_helper, ptr_at}, BACKENDS, BLIXT_CONNTRACK, GATEWAY_INDEXES, }; use common::{BackendKey, BACKENDS_ARRAY_CAPACITY}; pub fn handle_udp_ingress(ctx: TcContext) -> Result { - let ip_hdr: *mut iphdr = unsafe { ptr_at(&ctx, ETH_HDR_LEN) }?; + let ip_hdr: *mut Ipv4Hdr = unsafe { ptr_at(&ctx, EthHdr::LEN)? }; - let udp_header_offset = ETH_HDR_LEN + IP_HDR_LEN; + let udp_header_offset = EthHdr::LEN + Ipv4Hdr::LEN; - let udp_hdr: *mut udphdr = unsafe { ptr_at(&ctx, udp_header_offset)? }; + let udp_hdr: *mut UdpHdr = unsafe { ptr_at(&ctx, udp_header_offset) }?; - let original_daddr = unsafe { (*ip_hdr).daddr }; + let original_daddr = unsafe { (*ip_hdr).dst_addr }; let key = BackendKey { ip: u32::from_be(original_daddr), @@ -39,7 +39,7 @@ pub fn handle_udp_ingress(ctx: TcContext) -> Result { info!( &ctx, "Received a UDP packet destined for svc ip: {:i} at Port: {} ", - u32::from_be(unsafe { (*ip_hdr).daddr }), + u32::from_be(unsafe { (*ip_hdr).dst_addr }), u16::from_be(unsafe { (*udp_hdr).dest }) ); @@ -70,14 +70,14 @@ pub fn handle_udp_ingress(ctx: TcContext) -> Result { unsafe { BLIXT_CONNTRACK.insert( - &(*ip_hdr).saddr, + &(*ip_hdr).src_addr, &(original_daddr, (*udp_hdr).dest as u32), 0 as u64, )?; - (*ip_hdr).daddr = backend.daddr.to_be(); + (*ip_hdr).dst_addr = backend.daddr.to_be(); }; - if (ctx.data() + ETH_HDR_LEN + mem::size_of::()) > ctx.data_end() { + if (ctx.data() + EthHdr::LEN + Ipv4Hdr::LEN) > ctx.data_end() { info!(&ctx, "Iphdr is out of bounds"); return Ok(TC_ACT_PIPE); } @@ -90,7 +90,7 @@ pub fn handle_udp_ingress(ctx: TcContext) -> Result { mem::MaybeUninit::zeroed().assume_init(), 0, ip_hdr as *mut u32, - mem::size_of::() as u32, + Ipv4Hdr::LEN as u32, 0, ) } as u64; diff --git a/dataplane/ebpf/src/main.rs b/dataplane/ebpf/src/main.rs index e4b3b8b4..4e050d9b 100644 --- a/dataplane/ebpf/src/main.rs +++ b/dataplane/ebpf/src/main.rs @@ -11,13 +11,10 @@ SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) #[allow(non_snake_case)] #[allow(non_camel_case_types)] #[allow(dead_code)] -mod bindings; mod egress; mod ingress; mod utils; -use memoffset::offset_of; - use aya_bpf::{ bindings::{TC_ACT_OK, TC_ACT_PIPE, TC_ACT_SHOT}, macros::{classifier, map}, @@ -25,11 +22,15 @@ use aya_bpf::{ programs::TcContext, }; -use bindings::{ethhdr, iphdr}; use common::{BackendKey, BackendList, BPF_MAPS_CAPACITY}; use egress::{icmp::handle_icmp_egress, tcp::handle_tcp_egress}; use ingress::{tcp::handle_tcp_ingress, udp::handle_udp_ingress}; -use utils::{ETH_HDR_LEN, ETH_P_IP, IPPROTO_ICMP, IPPROTO_TCP, IPPROTO_UDP}; + +use network_types::{ + eth::{EthHdr, EtherType}, + ip::{IpProto, Ipv4Hdr}, +}; +use utils::ptr_at; // ----------------------------------------------------------------------------- // Maps @@ -64,23 +65,17 @@ pub fn tc_ingress(ctx: TcContext) -> i32 { // Make sure ip_forwarding is enabled on the interface this it attached to fn try_tc_ingress(ctx: TcContext) -> Result { - let h_proto = u16::from_be( - ctx.load(offset_of!(ethhdr, h_proto)) - .map_err(|_| TC_ACT_PIPE)?, - ); - - if h_proto != ETH_P_IP { - return Ok(TC_ACT_PIPE); - } - - let protocol = ctx - .load::(ETH_HDR_LEN + offset_of!(iphdr, protocol)) - .map_err(|_| TC_ACT_PIPE)?; - - match protocol { - IPPROTO_TCP => handle_tcp_ingress(ctx), - IPPROTO_UDP => handle_udp_ingress(ctx), - _ => Ok(TC_ACT_PIPE), + let eth_hdr: *const EthHdr = unsafe { ptr_at(&ctx, 0) }?; + match unsafe { *eth_hdr }.ether_type { + EtherType::Ipv4 => { + let ipv4hdr: *const Ipv4Hdr = unsafe { ptr_at(&ctx, EthHdr::LEN)? }; + match unsafe { *ipv4hdr }.proto { + IpProto::Tcp => handle_tcp_ingress(ctx), + IpProto::Udp => handle_udp_ingress(ctx), + _ => Ok(TC_ACT_PIPE), + } + } + _ => return Ok(TC_ACT_PIPE), } } @@ -100,23 +95,17 @@ pub fn tc_egress(ctx: TcContext) -> i32 { } fn try_tc_egress(ctx: TcContext) -> Result { - let h_proto = u16::from_be( - ctx.load(offset_of!(ethhdr, h_proto)) - .map_err(|_| TC_ACT_PIPE)?, - ); - - if h_proto != ETH_P_IP { - return Ok(TC_ACT_PIPE); - } - - let protocol = ctx - .load::(ETH_HDR_LEN + offset_of!(iphdr, protocol)) - .map_err(|_| TC_ACT_PIPE)?; - - match protocol { - IPPROTO_ICMP => handle_icmp_egress(ctx), - IPPROTO_TCP => handle_tcp_egress(ctx), - _ => Ok(TC_ACT_PIPE), + let eth_hdr: *const EthHdr = unsafe { ptr_at(&ctx, 0) }?; + match unsafe { *eth_hdr }.ether_type { + EtherType::Ipv4 => { + let ipv4hdr: *const Ipv4Hdr = unsafe { ptr_at(&ctx, EthHdr::LEN)? }; + match unsafe { *ipv4hdr }.proto { + IpProto::Icmp => handle_icmp_egress(ctx), + IpProto::Tcp => handle_tcp_egress(ctx), + _ => Ok(TC_ACT_PIPE), + } + } + _ => return Ok(TC_ACT_PIPE), } } diff --git a/dataplane/ebpf/src/utils.rs b/dataplane/ebpf/src/utils.rs index 365231bb..4cc8aaf0 100644 --- a/dataplane/ebpf/src/utils.rs +++ b/dataplane/ebpf/src/utils.rs @@ -5,24 +5,8 @@ SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ use core::mem; - use aya_bpf::{bindings::TC_ACT_OK, programs::TcContext}; -use crate::bindings::{ethhdr, iphdr}; - -// ----------------------------------------------------------------------------- -// Constants -// ----------------------------------------------------------------------------- - -pub const ETH_P_IP: u16 = 0x0800; - -pub const IPPROTO_TCP: u8 = 6; -pub const IPPROTO_UDP: u8 = 17; -pub const IPPROTO_ICMP: u8 = 1; - -pub const ETH_HDR_LEN: usize = mem::size_of::(); -pub const IP_HDR_LEN: usize = mem::size_of::(); - // ----------------------------------------------------------------------------- // Helper Functions // ----------------------------------------------------------------------------- @@ -37,7 +21,6 @@ pub unsafe fn ptr_at(ctx: &TcContext, offset: usize) -> Result<*mut T, i64> { if start + offset + len > end { return Err(TC_ACT_OK.into()); } - Ok((start + offset) as *mut T) } diff --git a/dataplane/xtask/src/codegen.rs b/dataplane/xtask/src/codegen.rs deleted file mode 100644 index 3af3b2d5..00000000 --- a/dataplane/xtask/src/codegen.rs +++ /dev/null @@ -1,22 +0,0 @@ -/* -Copyright 2023 The Kubernetes Authors. - -SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -*/ - -use aya_tool::generate::InputFile; -use std::{fs::File, io::Write, path::PathBuf}; - -pub fn generate() -> Result<(), anyhow::Error> { - let dir = PathBuf::from("ebpf/src"); - let names: Vec<&str> = vec!["ethhdr", "iphdr", "udphdr", "tcphdr", "icmphdr"]; - let bindings = aya_tool::generate( - InputFile::Btf(PathBuf::from("/sys/kernel/btf/vmlinux")), - &names, - &[], - )?; - // Write the bindings to the $OUT_DIR/bindings.rs file. - let mut out = File::create(dir.join("bindings.rs"))?; - write!(out, "{}", bindings)?; - Ok(()) -} diff --git a/dataplane/xtask/src/main.rs b/dataplane/xtask/src/main.rs index b6017168..b40d6cae 100644 --- a/dataplane/xtask/src/main.rs +++ b/dataplane/xtask/src/main.rs @@ -7,7 +7,6 @@ SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) // Remember to run `cargo install bindgen-cli` mod build_ebpf; -mod codegen; mod grpc; mod run; @@ -26,7 +25,6 @@ enum Command { BuildEbpf(build_ebpf::Options), Run(run::Options), GrpcClient(grpc::Options), - Codegen, } #[tokio::main] @@ -38,7 +36,6 @@ async fn main() { BuildEbpf(opts) => build_ebpf::build_ebpf(opts), Run(opts) => run::run(opts), GrpcClient(opts) => grpc::update(opts).await, - Codegen => codegen::generate(), }; if let Err(e) = ret {