diff options
Diffstat (limited to '')
-rw-r--r-- | src/libknot/xdp/bpf-user.h | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/libknot/xdp/bpf-user.h b/src/libknot/xdp/bpf-user.h new file mode 100644 index 0000000..37aac61 --- /dev/null +++ b/src/libknot/xdp/bpf-user.h @@ -0,0 +1,140 @@ +/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +/*! + * \file + * + * \brief XDP socket interface. + * + * \addtogroup xdp + * @{ + */ + +#pragma once + +#if USE_LIBXDP + #include <xdp/xsk.h> +#else + #include <bpf/xsk.h> +#endif + +#include "libknot/xdp/xdp.h" + +struct kxsk_iface { + /*! Interface name. */ + const char *if_name; + /*! Interface name index (derived from ifname). */ + int if_index; + /*! Network card queue id. */ + unsigned if_queue; + + /*! Configuration BPF map file descriptor. */ + int opts_map_fd; + /*! XSK BPF map file descriptor. */ + int xsks_map_fd; + + /*! BPF program object. */ + struct bpf_object *prog_obj; +}; + +struct kxsk_umem { + /*! Fill queue: passing memory frames to kernel - ready to receive. */ + struct xsk_ring_prod fq; + /*! Completion queue: passing memory frames from kernel - after send finishes. */ + struct xsk_ring_cons cq; + /*! Handle internal to libbpf. */ + struct xsk_umem *umem; + + /*! The memory frames. */ + struct umem_frame *frames; + /*! The number of free frames (for TX). */ + uint32_t tx_free_count; + /*! Stack of indices of the free frames (for TX). */ + uint16_t tx_free_indices[]; +}; + +struct knot_xdp_socket { + /*! Receive queue: passing arrived packets from kernel. */ + struct xsk_ring_cons rx; + /*! Transmit queue: passing packets to kernel for sending. */ + struct xsk_ring_prod tx; + /*! Information about memory frames for all the passed packets. */ + struct kxsk_umem *umem; + /*! Handle internal to libbpf. */ + struct xsk_socket *xsk; + + /*! Interface context. */ + const struct kxsk_iface *iface; + + /*! If non-NULL, it's a mocked socket with this send function. */ + int (*send_mock)(struct knot_xdp_socket *, const knot_xdp_msg_t[], uint32_t, uint32_t *); + + /*! The kernel has to be woken up by a syscall indication. */ + bool kernel_needs_wakeup; + + /*! The limit of frame size. */ + unsigned frame_limit; + + /*! Mapping of interface indices to VLAN tags. */ + uint16_t *vlan_map; + uint16_t vlan_map_max; +}; + +/*! + * \brief Set up BPF program and map for one XDP socket. + * + * \param if_name Name of the net iface (e.g. eth0). + * \param if_queue Network card queue id. + * \param load_bpf Insert BPF program into packet processing. + * \param generic_xdp Use generic XDP implementation instead of a native one. + * \param out_iface Output: created interface context. + * + * \return KNOT_E* or -errno + */ +int kxsk_iface_new(const char *if_name, unsigned if_queue, knot_xdp_load_bpf_t load_bpf, + bool generic_xdp, struct kxsk_iface **out_iface); + +/*! + * \brief Unload BPF maps for a socket. + * + * \note This keeps the loaded BPF program. We don't care. + * + * \param iface Interface context to be freed. + */ +void kxsk_iface_free(struct kxsk_iface *iface); + +/*! + * \brief Activate this AF_XDP socket through the BPF maps. + * + * \param iface Interface context. + * \param flags XDP filter configuration flags. + * \param udp_port UDP and/or TCP port to listen on if enabled via \a opts. + * \param quic_port QUIC/UDP port to listen on if enabled via \a opts. + * \param xsk Socket ctx. + * + * \return KNOT_E* or -errno + */ +int kxsk_socket_start(const struct kxsk_iface *iface, knot_xdp_filter_flag_t flags, + uint16_t udp_port, uint16_t quic_port, struct xsk_socket *xsk); + +/*! + * \brief Deactivate this AF_XDP socket through the BPF maps. + * + * \param iface Interface context. + */ +void kxsk_socket_stop(const struct kxsk_iface *iface); + +/*! @} */ |