Skip to content

Commit b549b8d

Browse files
authored
Merge pull request rex-rs#33 from rex-rs/electrode
- samples/electrode: replace reads of `iphdr.protocol` and `udphdr.dest` with `read_field!` - rex/utils: add `read_field!` - samples/electrode: fix the access of wrong index of magic bits in skb payload - samples/electrode: introduce PAXOS_PORT and MAGIC_BITS constants Signed-off-by: Jinghao Jia <[email protected]>
2 parents fe2943a + 56bce8e commit b549b8d

File tree

3 files changed

+78
-52
lines changed

3 files changed

+78
-52
lines changed

rex/src/utils.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,31 @@ where
258258
unsafe { AlignedMut::from_val(ptr.read_unaligned(), slice) }
259259
}
260260
}
261+
262+
/// Read a numeric field that is stored **big-endian** inside a header already
263+
/// sitting in `payload_slice` at offset `hdr_base`.
264+
///
265+
/// Example:
266+
/// ```
267+
/// let iphdr_base = size_of::<ethhdr>();
268+
/// let proto_be = read_field!(skb.data_slice, iphdr_base, iphdr, protocol, u8);
269+
/// match u8::from_be(proto_be) as u32 {
270+
/// IPPROTO_TCP => handle_tcp(),
271+
/// IPPROTO_UDP => handle_udp(),
272+
/// _ => {}
273+
/// }
274+
/// ```
275+
#[macro_export]
276+
macro_rules! read_field {
277+
($slice:expr, // payload slice
278+
$hdr_base:expr, // where this header starts inside the buffer
279+
$hdr:path, // concrete header type, for `offset_of!`
280+
$field:ident, // field we want
281+
$ty:ty // Rust type of that field (u8, u16, …)
282+
) => {{
283+
let start = $hdr_base + core::mem::offset_of!($hdr, $field);
284+
*$crate::utils::convert_slice_to_struct::<$ty>(
285+
&$slice[start..start + size_of::<$ty>()],
286+
)
287+
}};
288+
}

samples/electrode/src/common.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ pub(crate) const BROADCAST_SIGN_BIT: u32 = 1 << 31;
3131
pub(crate) const QUORUM_SIZE: u32 = (CLUSTER_SIZE as u32 + 1) >> 1;
3232
pub(crate) const QUORUM_BITSET_ENTRY: u32 = 1024; // must be 2^t
3333

34+
pub(crate) const PAXOS_PORT: u16 = 12345;
35+
pub(crate) const MAGIC_BITS: [u8; MAGIC_LEN] = [0x18, 0x03, 0x05, 0x20];
36+
3437
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
3538
#[repr(C)]
3639
pub(crate) enum ReplicaStatus {

samples/electrode/src/main.rs

Lines changed: 47 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
#![no_std]
22
#![no_main]
33
#![allow(non_camel_case_types)]
4+
#![allow(non_snake_case)]
45

56
extern crate rex;
67

7-
use core::mem::{offset_of, size_of, swap};
8+
use core::mem::{size_of, swap};
89

910
use rex::sched_cls::*;
1011
use rex::utils::*;
1112
use rex::xdp::*;
12-
use rex::{rex_printk, rex_tc, rex_xdp};
13+
use rex::{read_field, rex_printk, rex_tc, rex_xdp};
1314

1415
pub mod common;
1516
pub mod maps;
@@ -33,37 +34,36 @@ macro_rules! swap_field {
3334
fn fast_paxos_main(obj: &xdp, ctx: &mut xdp_md) -> Result {
3435
let header_len =
3536
size_of::<ethhdr>() + size_of::<iphdr>() + size_of::<udphdr>();
36-
let iphdr_start = size_of::<ethhdr>();
37-
let iphdr_end = iphdr_start + size_of::<iphdr>();
38-
let udphdr_end = iphdr_end + size_of::<udphdr>();
39-
40-
let protocol_start = iphdr_start + offset_of!(iphdr, protocol);
41-
let protocol = convert_slice_to_struct::<u8>(
42-
&ctx.data_slice[protocol_start..protocol_start + size_of::<u8>()],
43-
);
44-
45-
match u8::from_be(*protocol) as u32 {
37+
let iphdr_base = size_of::<ethhdr>();
38+
let iphdr_end = iphdr_base + size_of::<iphdr>();
39+
40+
match u8::from_be(read_field!(
41+
ctx.data_slice,
42+
iphdr_base,
43+
iphdr,
44+
protocol,
45+
u8
46+
)) as u32
47+
{
4648
IPPROTO_TCP => {
4749
// NOTE: currently we only take care of UDP memcached
4850
}
4951
IPPROTO_UDP => {
50-
let port_start = iphdr_end + offset_of!(udphdr, dest);
51-
let port = u16::from_be(*convert_slice_to_struct::<u16>(
52-
&ctx.data_slice[port_start..port_start + size_of::<u16>()],
52+
let port = u16::from_be(read_field!(
53+
ctx.data_slice,
54+
iphdr_end,
55+
udphdr,
56+
dest,
57+
u16
5358
));
59+
5460
let payload = &mut ctx.data_slice[header_len..];
5561

5662
// port check, our process bound to 12345.
5763
// don't have magic bits...
58-
if port != 12345 || payload.len() < MAGIC_LEN + size_of::<u64>() {
59-
return Ok(XDP_PASS as i32);
60-
}
61-
62-
// NOTE: currently, we don't support reassembly.
63-
if payload[0] != 0x18 ||
64-
payload[1] != 0x03 ||
65-
payload[2] != 0x05 ||
66-
payload[3] != 0x20
64+
if port != PAXOS_PORT ||
65+
payload.len() < MAGIC_LEN + size_of::<u64>() ||
66+
!payload.starts_with(&MAGIC_BITS)
6767
{
6868
return Ok(XDP_PASS as i32);
6969
}
@@ -79,44 +79,39 @@ fn fast_paxos_main(obj: &xdp, ctx: &mut xdp_md) -> Result {
7979

8080
#[rex_tc]
8181
fn fast_broad_cast_main(obj: &sched_cls, skb: &mut __sk_buff) -> Result {
82-
let mut header_len =
82+
let header_len =
8383
size_of::<iphdr>() + size_of::<ethhdr>() + size_of::<udphdr>();
84-
let iphdr_start = size_of::<ethhdr>();
85-
let iphdr_end = iphdr_start + size_of::<iphdr>();
84+
let iphdr_base = size_of::<ethhdr>();
85+
let iphdr_end = iphdr_base + size_of::<iphdr>();
8686

8787
// check if the packet is long enough
8888
if skb.data_slice.len() <= header_len {
8989
return Ok(TC_ACT_OK as i32);
9090
}
9191

92-
let protocol_start = iphdr_start + offset_of!(iphdr, protocol);
93-
let protocol = convert_slice_to_struct::<u8>(
94-
&skb.data_slice[protocol_start..protocol_start + size_of::<u8>()],
95-
);
96-
match u8::from_be(*protocol) as u32 {
92+
match u8::from_be(read_field!(
93+
skb.data_slice,
94+
iphdr_base,
95+
iphdr,
96+
protocol,
97+
u8
98+
)) as u32
99+
{
97100
IPPROTO_UDP => {
98-
// only port 12345 is allowed
99-
let port_start = iphdr_end + offset_of!(udphdr, dest);
100-
let port = u16::from_be(*convert_slice_to_struct::<u16>(
101-
&skb.data_slice[port_start..port_start + size_of::<u16>()],
101+
let port = u16::from_be(read_field!(
102+
skb.data_slice,
103+
iphdr_end,
104+
udphdr,
105+
dest,
106+
u16
102107
));
103-
if port != 12345 {
104-
return Ok(TC_ACT_OK as i32);
105-
}
106-
107-
// check for the magic bits
108-
header_len += MAGIC_LEN + size_of::<u64>();
109108

110-
if skb.data_slice.len() < header_len {
111-
rex_printk!("data_slice.len() < header_len\n").ok();
112-
return Ok(TC_ACT_OK as i32);
113-
}
114-
let payload = &skb.data_slice;
115-
116-
if payload[0] != 0x18 ||
117-
payload[1] != 0x03 ||
118-
payload[2] != 0x05 ||
119-
payload[3] != 0x20
109+
let payload = &skb.data_slice[header_len..];
110+
// check for the magic bits and Paxos port
111+
// only port 12345 is allowed
112+
if port != PAXOS_PORT ||
113+
payload.len() < MAGIC_LEN + size_of::<u64>() ||
114+
!payload.starts_with(&MAGIC_BITS)
120115
{
121116
return Ok(TC_ACT_OK as i32);
122117
}

0 commit comments

Comments
 (0)