diff --git a/src/source-af-xdp.c b/src/source-af-xdp.c index f68f7f5724e9..8f4b6071bd75 100644 --- a/src/source-af-xdp.c +++ b/src/source-af-xdp.c @@ -61,8 +61,10 @@ #include "util-validate.h" #ifdef HAVE_AF_XDP -#include #include +#include +#include +#include #endif #if HAVE_LINUX_IF_ETHER_H @@ -113,7 +115,9 @@ TmEcode NoAFXDPSupportExit(ThreadVars *tv, const void *initdata, void **data) #else /* We have AF_XDP support */ #define POLL_TIMEOUT 100 -#define NUM_FRAMES XSK_RING_PROD__DEFAULT_NUM_DESCS +#define NUM_FRAMES_PROD XSK_RING_PROD__DEFAULT_NUM_DESCS +#define NUM_FRAMES_CONS XSK_RING_CONS__DEFAULT_NUM_DESCS +#define NUM_FRAMES NUM_FRAMES_PROD #define FRAME_SIZE XSK_UMEM__DEFAULT_FRAME_SIZE #define MEM_BYTES (NUM_FRAMES * FRAME_SIZE * 2) #define RECONNECT_TIMEOUT 500000 @@ -636,14 +640,14 @@ static TmEcode ReceiveAFXDPThreadInit(ThreadVars *tv, const void *initdata, void ptv->threads = afxdpconfig->threads; /* Socket configuration */ - ptv->xsk.cfg.rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS; - ptv->xsk.cfg.tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS; + ptv->xsk.cfg.rx_size = NUM_FRAMES_CONS; + ptv->xsk.cfg.tx_size = NUM_FRAMES_PROD; ptv->xsk.cfg.xdp_flags = afxdpconfig->mode; ptv->xsk.cfg.bind_flags = afxdpconfig->bind_flags; /* UMEM configuration */ - ptv->umem.cfg.fill_size = XSK_RING_PROD__DEFAULT_NUM_DESCS * 2; - ptv->umem.cfg.comp_size = XSK_RING_CONS__DEFAULT_NUM_DESCS; + ptv->umem.cfg.fill_size = NUM_FRAMES_PROD * 2; + ptv->umem.cfg.comp_size = NUM_FRAMES_CONS; ptv->umem.cfg.frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE; ptv->umem.cfg.frame_headroom = XSK_UMEM__DEFAULT_FRAME_HEADROOM; ptv->umem.cfg.flags = afxdpconfig->mem_alignment; @@ -824,15 +828,60 @@ static TmEcode ReceiveAFXDPLoop(ThreadVars *tv, void *data, void *slot) SCReturnInt(TM_ECODE_OK); } +/** + * \brief function to unload an AF_XDP program + * + */ +static void RunModeAFXDPRemoveProg(char *iface_name) +{ + unsigned int ifindex = if_nametoindex(iface_name); + + struct xdp_multiprog *progs = xdp_multiprog__get_from_ifindex(ifindex); + if (progs == NULL) { + return; + } + enum xdp_attach_mode mode = xdp_multiprog__attach_mode(progs); + + struct xdp_program *prog = NULL; + + // loop through the multiprogram struct, removing all the programs + for (prog = xdp_multiprog__next_prog(NULL, progs); prog; + prog = xdp_multiprog__next_prog(prog, progs)) { + int ret = xdp_program__detach(prog, ifindex, mode, 0); + if (ret) { + SCLogDebug("Error: cannot detatch XDP program: %s\n", strerror(errno)); + } + } + + prog = xdp_multiprog__main_prog(progs); + if (xdp_program__is_attached(prog, ifindex) != XDP_MODE_UNSPEC) { + int ret = xdp_program__detach(prog, ifindex, mode, 0); + if (ret) { + SCLogDebug("Error: cannot detatch XDP program: %s\n", strerror(errno)); + } + } +} + /** * \brief DeInit function closes af-xdp socket at exit. * \param tv pointer to ThreadVars * \param data pointer that gets cast into AFXDPPThreadVars for ptv */ +static SCMutex sync_deinit = SCMUTEX_INITIALIZER; + static TmEcode ReceiveAFXDPThreadDeinit(ThreadVars *tv, void *data) { AFXDPThreadVars *ptv = (AFXDPThreadVars *)data; + /* + * If AF_XDP is enabled, the program must be detached before the AF_XDP sockets + * are closed to mitigate a bug that causes an IO_PAGEFAULT in linux kernel + * version 5.19, unknown as of now what other versions this affects. + */ + SCMutexLock(&sync_deinit); + RunModeAFXDPRemoveProg(ptv->iface); + SCMutexUnlock(&sync_deinit); + if (ptv->xsk.xsk) { xsk_socket__delete(ptv->xsk.xsk); ptv->xsk.xsk = NULL; @@ -924,4 +973,4 @@ static TmEcode DecodeAFXDPThreadDeinit(ThreadVars *tv, void *data) /* eof */ /** * @} - */ + */ \ No newline at end of file