s2n_quic_platform/bpf/
program.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use super::{instruction::Dialect, Instruction};
5use core::{fmt, mem::size_of};
6use libc::sock_fprog;
7use std::{io, os::fd::AsRawFd};
8
9pub struct Program<'a, D: Dialect> {
10    instructions: &'a [Instruction<D>],
11}
12
13impl<'a, D: Dialect> Program<'a, D> {
14    #[inline]
15    pub const fn new(instructions: &'a [Instruction<D>]) -> Self {
16        if instructions.len() > D::MAX_INSTRUCTIONS {
17            panic!("program too large");
18        }
19        Self { instructions }
20    }
21
22    #[inline]
23    pub fn attach<S: AsRawFd>(&self, socket: &S) -> io::Result<()> {
24        let prog = sock_fprog {
25            filter: self.instructions.as_ptr() as *const _ as *mut _,
26            len: self.instructions.len() as _,
27        };
28
29        let ret = unsafe {
30            libc::setsockopt(
31                socket.as_raw_fd(),
32                libc::SOL_SOCKET,
33                D::SOCKOPT as _,
34                &prog as *const _ as *const _,
35                size_of::<sock_fprog>() as _,
36            )
37        };
38
39        if ret < 0 {
40            Err(io::Error::last_os_error())
41        } else {
42            Ok(())
43        }
44    }
45}
46
47impl<D: Dialect> fmt::Debug for Program<'_, D> {
48    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49        f.debug_struct("Program")
50            .field("instructions", &self.instructions)
51            .finish()
52    }
53}
54
55impl<D: Dialect> fmt::Display for Program<'_, D> {
56    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57        for (idx, inst) in self.instructions.iter().enumerate() {
58            D::display(inst, f, Some(idx))?;
59            writeln!(f)?;
60        }
61        Ok(())
62    }
63}