From cc033f19603b4cab9570bb7b42f92b60c7c894dc Mon Sep 17 00:00:00 2001 From: "amir.boussejra" Date: Mon, 3 Aug 2026 11:40:12 +0200 Subject: [PATCH 1/5] af-xdp: make WriteLinuxTunables resolve real netdev name in case of altname used in suricata config WriteLinuxTunables built the sysfs path from the configured interface name. When an altname is used in the config, sysfs only exposes the real netdev name and writing gro_flush_timeout/napi_defer_hard_irqs failed. Resolve the real name via if_indextoname before building the path. Ticket: #8780 --- src/source-af-xdp.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/source-af-xdp.c b/src/source-af-xdp.c index c95a5ede2b..9256bff5be 100644 --- a/src/source-af-xdp.c +++ b/src/source-af-xdp.c @@ -354,9 +354,17 @@ static TmEcode InitFillRing(AFXDPThreadVars *ptv, const uint32_t cnt) static TmEcode WriteLinuxTunables(AFXDPThreadVars *ptv) { char fname[SYSFS_MAX_FILENAME_SIZE]; + char ifname[IF_NAMESIZE]; - if (snprintf(fname, SYSFS_MAX_FILENAME_SIZE, "class/net/%s/gro_flush_timeout", ptv->iface) < - 0) { + /* The configured interface may be an alternative name (e.g. "mon0"), but + * sysfs only exposes a directory for the real netdev name. */ + if (if_indextoname(ptv->ifindex, ifname) == NULL) { + SCLogError("Could not resolve interface name for %s (ifindex %u): %s", ptv->iface, + ptv->ifindex, strerror(errno)); + SCReturnInt(TM_ECODE_FAILED); + } + + if (snprintf(fname, SYSFS_MAX_FILENAME_SIZE, "class/net/%s/gro_flush_timeout", ifname) < 0) { SCReturnInt(TM_ECODE_FAILED); } @@ -364,8 +372,7 @@ static TmEcode WriteLinuxTunables(AFXDPThreadVars *ptv) SCReturnInt(TM_ECODE_FAILED); } - if (snprintf(fname, SYSFS_MAX_FILENAME_SIZE, "class/net/%s/napi_defer_hard_irqs", ptv->iface) < - 0) { + if (snprintf(fname, SYSFS_MAX_FILENAME_SIZE, "class/net/%s/napi_defer_hard_irqs", ifname) < 0) { SCReturnInt(TM_ECODE_FAILED); } From 87a05e9aea63893875cc8080a5c96fb1aa895ab0 Mon Sep 17 00:00:00 2001 From: "amir.boussejra" Date: Mon, 3 Aug 2026 11:47:07 +0200 Subject: [PATCH 2/5] af-xdp: fix queue assignment with multiple capture interfaces The XSK queue id counter was global, so with two capture interfaces the second interface's threads got queue ids continuing after the first interface's, and xsk_socket__create failed for queues that do not exist on that device. Make the counter per interface config and assign ids with a single atomic fetch-and-add at thread init. Ticket: #8780 --- src/runmode-af-xdp.c | 1 + src/source-af-xdp.c | 23 ++++------------------- src/source-af-xdp.h | 1 + 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/runmode-af-xdp.c b/src/runmode-af-xdp.c index 017b1d782f..18878f1a91 100644 --- a/src/runmode-af-xdp.c +++ b/src/runmode-af-xdp.c @@ -178,6 +178,7 @@ static void *ParseAFXDPConfig(const char *iface) aconf->gro_flush_timeout = DEFAULT_GRO_FLUSH_TIMEOUT; aconf->napi_defer_hard_irqs = DEFAULT_NAPI_HARD_IRQS; aconf->mem_alignment = XSK_UMEM__DEFAULT_FLAGS; + SC_ATOMIC_INIT(aconf->queue_idx); /* Find initial node */ af_xdp_node = SCConfGetNode("af-xdp"); diff --git a/src/source-af-xdp.c b/src/source-af-xdp.c index 9256bff5be..284e36482d 100644 --- a/src/source-af-xdp.c +++ b/src/source-af-xdp.c @@ -126,7 +126,6 @@ enum state { AFXDP_STATE_DOWN, AFXDP_STATE_UP }; struct XskInitProtect { SCMutex queue_protect; - SC_ATOMIC_DECLARE(uint8_t, queue_num); } xsk_protect; struct UmemInfo { @@ -279,19 +278,6 @@ TmEcode AFXDPQueueProtectionInit(void) SCEnter(); SCMutexInit(&xsk_protect.queue_protect, NULL); - SC_ATOMIC_SET(xsk_protect.queue_num, 0); - SCReturnInt(TM_ECODE_OK); -} - -static TmEcode AFXDPAssignQueueID(AFXDPThreadVars *ptv) -{ - if (!ptv->xsk.queue.assigned) { - ptv->xsk.queue.queue_num = SC_ATOMIC_GET(xsk_protect.queue_num); - SC_ATOMIC_ADD(xsk_protect.queue_num, 1); - - /* Queue only needs assigned once, on startup */ - ptv->xsk.queue.assigned = true; - } SCReturnInt(TM_ECODE_OK); } @@ -439,11 +425,6 @@ static TmEcode OpenXSKSocket(AFXDPThreadVars *ptv) SCMutexLock(&xsk_protect.queue_protect); - if (AFXDPAssignQueueID(ptv) != TM_ECODE_OK) { - SCLogError("Failed to assign queue ID"); - SCReturnInt(TM_ECODE_FAILED); - } - if ((ret = xsk_socket__create(&ptv->xsk.xsk, ptv->livedev->dev, ptv->xsk.queue.queue_num, ptv->umem.umem, &ptv->xsk.rx, &ptv->xsk.tx, &ptv->xsk.cfg))) { SCLogError("Failed to create socket: %s", strerror(-ret)); @@ -667,6 +648,10 @@ static TmEcode ReceiveAFXDPThreadInit(ThreadVars *tv, const void *initdata, void ptv->gro_flush_timeout = afxdpconfig->gro_flush_timeout; ptv->napi_defer_hard_irqs = afxdpconfig->napi_defer_hard_irqs; + /* threads of an interface init in parallel, claim a queue index atomically */ + ptv->xsk.queue.queue_num = SC_ATOMIC_ADD(afxdpconfig->queue_idx, 1); + ptv->xsk.queue.assigned = true; + /* Stats registration */ ptv->capture_afxdp_packets = StatsRegisterCounter("capture.afxdp_packets", &ptv->tv->stats); ptv->capture_kernel_drops = StatsRegisterCounter("capture.kernel_drops", &ptv->tv->stats); diff --git a/src/source-af-xdp.h b/src/source-af-xdp.h index 931f265acf..9c516714f4 100644 --- a/src/source-af-xdp.h +++ b/src/source-af-xdp.h @@ -42,6 +42,7 @@ typedef struct AFXDPIfaceConfig { uint32_t gro_flush_timeout; uint32_t napi_defer_hard_irqs; + SC_ATOMIC_DECLARE(uint32_t, queue_idx); SC_ATOMIC_DECLARE(unsigned int, ref); void (*DerefFunc)(void *); } AFXDPIfaceConfig; From 3ffd643a1672b3805231a3033a52f488d78c9f8e Mon Sep 17 00:00:00 2001 From: "amir.boussejra" Date: Mon, 3 Aug 2026 11:58:57 +0200 Subject: [PATCH 3/5] af-xdp: make UMEM size configurable UMEM size was hardcoded to XSK ring default descriptors * 2 with default frame size. Add umem-frames and frame-size options to the af-xdp section so buffer memory can be tuned per interface. Ticket: #8780 --- src/runmode-af-xdp.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ src/source-af-xdp.c | 37 +++++++++++++++++++----------------- src/source-af-xdp.h | 6 ++++++ suricata.yaml.in | 6 ++++++ 4 files changed, 77 insertions(+), 17 deletions(-) diff --git a/src/runmode-af-xdp.c b/src/runmode-af-xdp.c index 18878f1a91..6ced7c7091 100644 --- a/src/runmode-af-xdp.c +++ b/src/runmode-af-xdp.c @@ -83,6 +83,16 @@ void RunModeIdsAFXDPRegister(void) #define DEFAULT_BUSY_POLL_BUDGET 64 #define DEFAULT_GRO_FLUSH_TIMEOUT 2000000 #define DEFAULT_NAPI_HARD_IRQS 2 +#define DEFAULT_RX_RING_SIZE XSK_RING_CONS__DEFAULT_NUM_DESCS +#define DEFAULT_UMEM_FRAMES (XSK_RING_PROD__DEFAULT_NUM_DESCS * 2) +#define DEFAULT_FRAME_SIZE XSK_UMEM__DEFAULT_FRAME_SIZE + +/* Function to check if x is power of 2 + * https://www.geeksforgeeks.org/c/c-program-to-find-whether-a-no-is-power-of-two/ */ +static bool isPowerOfTwo(uint32_t x) +{ + return x && (!(x & (x - 1))); +} static void AFXDPDerefConfig(void *conf) { @@ -179,6 +189,9 @@ static void *ParseAFXDPConfig(const char *iface) aconf->napi_defer_hard_irqs = DEFAULT_NAPI_HARD_IRQS; aconf->mem_alignment = XSK_UMEM__DEFAULT_FLAGS; SC_ATOMIC_INIT(aconf->queue_idx); + aconf->rx_ring_size = DEFAULT_RX_RING_SIZE; + aconf->umem_frames = DEFAULT_UMEM_FRAMES; + aconf->frame_size = DEFAULT_FRAME_SIZE; /* Find initial node */ af_xdp_node = SCConfGetNode("af-xdp"); @@ -253,6 +266,38 @@ static void *ParseAFXDPConfig(const char *iface) } } + /* UMEM count of frames */ + if (SCConfGetChildValueIntWithDefault(if_root, if_default, "umem-frames", &conf_val_int) == 1) { + if (conf_val_int > 0) { + aconf->umem_frames = (uint32_t)conf_val_int; + } + } + if (!isPowerOfTwo(aconf->umem_frames)) { + FatalError("%s: af-xdp umem-frames (%u) must be a power of two", aconf->iface, + aconf->umem_frames); + } + aconf->rx_ring_size = aconf->umem_frames / 2; + + /* Size of one UMEM frame in bytes. Must be a power of two. */ + if (SCConfGetChildValueIntWithDefault(if_root, if_default, "frame-size", &conf_val_int) == 1) { + if (conf_val_int > 0) { + aconf->frame_size = (uint32_t)conf_val_int; + } + } + if (!isPowerOfTwo(aconf->frame_size)) { + FatalError("%s: af-xdp frame-size (%u) must be a power of two", aconf->iface, + aconf->frame_size); + } + + SCLogConfig("%s: af-xdp: rx-ring-size %u, umem %u frames of %u bytes: %" PRIu64 + " bytes (%.1f MiB) per thread, %" PRIu64 " bytes (%.1f MiB) over %d threads", + aconf->iface, aconf->rx_ring_size, aconf->umem_frames, aconf->frame_size, + (uint64_t)aconf->umem_frames * aconf->frame_size, + (double)aconf->umem_frames * aconf->frame_size / (1024 * 1024), + (uint64_t)aconf->umem_frames * aconf->frame_size * aconf->threads, + (double)aconf->umem_frames * aconf->frame_size * aconf->threads / (1024 * 1024), + aconf->threads); + /* Busy polling options */ if (SCConfGetChildValueBoolWithDefault(if_root, if_default, "enable-busy-poll", &conf_val) == 1) { diff --git a/src/source-af-xdp.c b/src/source-af-xdp.c index 284e36482d..4cc383bc3a 100644 --- a/src/source-af-xdp.c +++ b/src/source-af-xdp.c @@ -114,11 +114,6 @@ TmEcode NoAFXDPSupportExit(ThreadVars *tv, const void *initdata, void **data) #else /* We have AF_XDP support */ #define POLL_TIMEOUT 100 -#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 /* Interface state */ @@ -135,6 +130,7 @@ struct UmemInfo { struct xsk_ring_cons cq; struct xsk_umem_config cfg; int mmap_alignment_flag; + uint64_t mem_bytes; }; struct QueueAssignment { @@ -293,7 +289,7 @@ static void AFXDPAllThreadsRunning(AFXDPThreadVars *ptv) static TmEcode AcquireBuffer(AFXDPThreadVars *ptv) { int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS | ptv->umem.mmap_alignment_flag; - ptv->umem.buf = mmap(NULL, MEM_BYTES, PROT_READ | PROT_WRITE, mmap_flags, -1, 0); + ptv->umem.buf = mmap(NULL, ptv->umem.mem_bytes, PROT_READ | PROT_WRITE, mmap_flags, -1, 0); if (ptv->umem.buf == MAP_FAILED) { SCLogError("mmap: failed to acquire memory"); @@ -305,8 +301,8 @@ static TmEcode AcquireBuffer(AFXDPThreadVars *ptv) static TmEcode ConfigureXSKUmem(AFXDPThreadVars *ptv) { - if (xsk_umem__create(&ptv->umem.umem, ptv->umem.buf, MEM_BYTES, &ptv->umem.fq, &ptv->umem.cq, - &ptv->umem.cfg)) { + if (xsk_umem__create(&ptv->umem.umem, ptv->umem.buf, ptv->umem.mem_bytes, &ptv->umem.fq, + &ptv->umem.cq, &ptv->umem.cfg)) { SCLogError("failed to create umem: %s", strerror(errno)); SCReturnInt(TM_ECODE_FAILED); } @@ -325,7 +321,7 @@ static TmEcode InitFillRing(AFXDPThreadVars *ptv, const uint32_t cnt) } for (uint32_t i = 0; i < cnt; i++) { - *xsk_ring_prod__fill_addr(&ptv->umem.fq, idx_fq++) = i * FRAME_SIZE; + *xsk_ring_prod__fill_addr(&ptv->umem.fq, idx_fq++) = (uint64_t)i * ptv->umem.cfg.frame_size; } xsk_ring_prod__submit(&ptv->umem.fq, cnt); @@ -466,7 +462,7 @@ static TmEcode AFXDPSocketCreation(AFXDPThreadVars *ptv) SCReturnInt(TM_ECODE_FAILED); } - if (InitFillRing(ptv, NUM_FRAMES * 2) != TM_ECODE_OK) { + if (InitFillRing(ptv, ptv->umem.cfg.fill_size) != TM_ECODE_OK) { SCReturnInt(TM_ECODE_FAILED); } @@ -624,15 +620,17 @@ static TmEcode ReceiveAFXDPThreadInit(ThreadVars *tv, const void *initdata, void ptv->threads = afxdpconfig->threads; /* Socket configuration */ - ptv->xsk.cfg.rx_size = NUM_FRAMES_CONS; - ptv->xsk.cfg.tx_size = NUM_FRAMES_PROD; + ptv->xsk.cfg.rx_size = afxdpconfig->rx_ring_size; + ptv->xsk.cfg.tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS; ptv->xsk.cfg.xdp_flags = afxdpconfig->mode; ptv->xsk.cfg.bind_flags = afxdpconfig->bind_flags; - /* UMEM configuration */ - 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; + /* UMEM configuration, the fill ring is sized to hold the whole UMEM so + * every frame can be handed to the kernel at once. */ + ptv->umem.mem_bytes = (uint64_t)afxdpconfig->umem_frames * afxdpconfig->frame_size; + ptv->umem.cfg.fill_size = afxdpconfig->umem_frames; + ptv->umem.cfg.comp_size = XSK_RING_CONS__DEFAULT_NUM_DESCS; + ptv->umem.cfg.frame_size = afxdpconfig->frame_size; ptv->umem.cfg.frame_headroom = XSK_UMEM__DEFAULT_FRAME_HEADROOM; ptv->umem.cfg.flags = afxdpconfig->mem_alignment; @@ -667,6 +665,11 @@ static TmEcode ReceiveAFXDPThreadInit(ThreadVars *tv, const void *initdata, void ptv->capture_afxdp_acquire_pkt_failed = StatsRegisterCounter("capture.afxdp.acquire_pkt_failed", &ptv->tv->stats); + SCLogPerf("%s: (%s) umem params: frame_size=%u frame_nr=%u rx_ring=%u (mem: %" PRIu64 + ", %.1f MiB)", + ptv->iface, tv->name, ptv->umem.cfg.frame_size, ptv->umem.cfg.fill_size, + ptv->xsk.cfg.rx_size, ptv->umem.mem_bytes, (double)ptv->umem.mem_bytes / (1024 * 1024)); + /* Reserve memory for umem */ if (AcquireBuffer(ptv) != TM_ECODE_OK) { SCFree(ptv); @@ -883,7 +886,7 @@ static TmEcode ReceiveAFXDPThreadDeinit(ThreadVars *tv, void *data) xsk_umem__delete(ptv->umem.umem); ptv->umem.umem = NULL; } - munmap(ptv->umem.buf, MEM_BYTES); + munmap(ptv->umem.buf, ptv->umem.mem_bytes); SCFree(ptv); SCReturnInt(TM_ECODE_OK); diff --git a/src/source-af-xdp.h b/src/source-af-xdp.h index 9c516714f4..6a71c77e53 100644 --- a/src/source-af-xdp.h +++ b/src/source-af-xdp.h @@ -42,6 +42,12 @@ typedef struct AFXDPIfaceConfig { uint32_t gro_flush_timeout; uint32_t napi_defer_hard_irqs; + /* UMEM size in frames and derived RX ring depth, per thread */ + uint32_t umem_frames; + uint32_t rx_ring_size; + /* Size of one UMEM frame in bytes */ + uint32_t frame_size; + SC_ATOMIC_DECLARE(uint32_t, queue_idx); SC_ATOMIC_DECLARE(unsigned int, ref); void (*DerefFunc)(void *); diff --git a/suricata.yaml.in b/suricata.yaml.in index 055668b1c5..5fe3c8e624 100644 --- a/suricata.yaml.in +++ b/suricata.yaml.in @@ -785,6 +785,12 @@ af-xdp: # Note: unaligned chunk mode uses hugepages, so the required number # of pages must be available. #mem-unaligned: no + # UMEM size, expressed in frames of frame-size bytes (power of two) + #umem-frames: 4096 + # Size of one UMEM frame in bytes. A frame holds a single packet, so + # it must be large enough for the biggest packet (MTU + headroom). + # Valid values are effectively 2048 or 4096: a power of two. + #frame-size: 4096 # The following options configure the prefer-busy-polling socket # options. The polling time and budget can be edited here. # Possible values are: From 134c45d796f1d3526c06f9c7273e2d2e8e3e0062 Mon Sep 17 00:00:00 2001 From: "amir.boussejra" Date: Mon, 3 Aug 2026 11:59:35 +0200 Subject: [PATCH 4/5] af-xdp: Add more statistics to stats.log from XSK Expose xsk_socket stats in stats.log: capture.afxdp.rx_dropped, rx_invalid_descs, rx_ring_full and fill_ring_empty. Helps diagnose whether kernel drops come from. Ticket: #8780 --- src/source-af-xdp.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/source-af-xdp.c b/src/source-af-xdp.c index 4cc383bc3a..f1826be457 100644 --- a/src/source-af-xdp.c +++ b/src/source-af-xdp.c @@ -191,6 +191,10 @@ typedef struct AFXDPThreadVars_ { StatsCounterId capture_afxdp_empty_reads; StatsCounterId capture_afxdp_failed_reads; StatsCounterId capture_afxdp_acquire_pkt_failed; + StatsCounterId capture_afxdp_rx_dropped; + StatsCounterId capture_afxdp_rx_invalid_descs; + StatsCounterId capture_afxdp_rx_ring_full; + StatsCounterId capture_afxdp_fill_ring_empty; } AFXDPThreadVars; static TmEcode ReceiveAFXDPThreadInit(ThreadVars *, const void *, void **); @@ -247,13 +251,30 @@ static inline void AFXDPDumpCounters(AFXDPThreadVars *ptv) rx_dropped - StatsCounterGetLocalValue(&ptv->tv->stats, ptv->capture_kernel_drops)); StatsCounterAddI64(&ptv->tv->stats, ptv->capture_afxdp_packets, ptv->pkts); + StatsCounterAddI64(&ptv->tv->stats, ptv->capture_afxdp_rx_dropped, + stats.rx_dropped - + StatsCounterGetLocalValue(&ptv->tv->stats, ptv->capture_afxdp_rx_dropped)); + StatsCounterAddI64(&ptv->tv->stats, ptv->capture_afxdp_rx_invalid_descs, + stats.rx_invalid_descs - StatsCounterGetLocalValue(&ptv->tv->stats, + ptv->capture_afxdp_rx_invalid_descs)); + StatsCounterAddI64(&ptv->tv->stats, ptv->capture_afxdp_rx_ring_full, + stats.rx_ring_full - StatsCounterGetLocalValue( + &ptv->tv->stats, ptv->capture_afxdp_rx_ring_full)); + StatsCounterAddI64(&ptv->tv->stats, ptv->capture_afxdp_fill_ring_empty, + stats.rx_fill_ring_empty_descs - StatsCounterGetLocalValue(&ptv->tv->stats, + ptv->capture_afxdp_fill_ring_empty)); + (void)SC_ATOMIC_SET(ptv->livedev->drop, rx_dropped); (void)SC_ATOMIC_ADD(ptv->livedev->pkts, ptv->pkts); - SCLogDebug("(%s) Kernel: Packets %" PRIu64 ", bytes %" PRIu64 ", dropped %" PRIu64 "", + SCLogDebug("(%s) Kernel: Packets %" PRIu64 ", bytes %" PRIu64 ", dropped %" PRIu64 + " (rx_dropped %" PRIu64 ", rx_ring_full %" PRIu64 ", fill_ring_empty %" PRIu64 + ", rx_invalid_descs %" PRIu64 ")", ptv->tv->name, StatsCounterGetLocalValue(&ptv->tv->stats, ptv->capture_afxdp_packets), ptv->bytes, - StatsCounterGetLocalValue(&ptv->tv->stats, ptv->capture_kernel_drops)); + StatsCounterGetLocalValue(&ptv->tv->stats, ptv->capture_kernel_drops), + stats.rx_dropped, stats.rx_ring_full, stats.rx_fill_ring_empty_descs, + stats.rx_invalid_descs); ptv->pkts = 0; } @@ -664,6 +685,14 @@ static TmEcode ReceiveAFXDPThreadInit(ThreadVars *tv, const void *initdata, void StatsRegisterCounter("capture.afxdp.failed_reads", &ptv->tv->stats); ptv->capture_afxdp_acquire_pkt_failed = StatsRegisterCounter("capture.afxdp.acquire_pkt_failed", &ptv->tv->stats); + ptv->capture_afxdp_rx_dropped = + StatsRegisterCounter("capture.afxdp.rx_dropped", &ptv->tv->stats); + ptv->capture_afxdp_rx_invalid_descs = + StatsRegisterCounter("capture.afxdp.rx_invalid_descs", &ptv->tv->stats); + ptv->capture_afxdp_rx_ring_full = + StatsRegisterCounter("capture.afxdp.rx_ring_full", &ptv->tv->stats); + ptv->capture_afxdp_fill_ring_empty = + StatsRegisterCounter("capture.afxdp.fill_ring_empty", &ptv->tv->stats); SCLogPerf("%s: (%s) umem params: frame_size=%u frame_nr=%u rx_ring=%u (mem: %" PRIu64 ", %.1f MiB)", From 51df20d77fd15836dc07cce9602b479cac9438e0 Mon Sep 17 00:00:00 2001 From: Amir Boussejra Date: Fri, 11 Sep 2026 11:06:18 +0200 Subject: [PATCH 5/5] af-xdp: do not create a TX ring AF_XDP capture is receive only Ticket: #8780 --- src/source-af-xdp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/source-af-xdp.c b/src/source-af-xdp.c index f1826be457..c620cbd8ba 100644 --- a/src/source-af-xdp.c +++ b/src/source-af-xdp.c @@ -140,7 +140,6 @@ struct QueueAssignment { struct XskSockInfo { struct xsk_ring_cons rx; - struct xsk_ring_prod tx; struct xsk_socket *xsk; /* Queue assignment structure */ @@ -443,7 +442,7 @@ static TmEcode OpenXSKSocket(AFXDPThreadVars *ptv) SCMutexLock(&xsk_protect.queue_protect); if ((ret = xsk_socket__create(&ptv->xsk.xsk, ptv->livedev->dev, ptv->xsk.queue.queue_num, - ptv->umem.umem, &ptv->xsk.rx, &ptv->xsk.tx, &ptv->xsk.cfg))) { + ptv->umem.umem, &ptv->xsk.rx, NULL, &ptv->xsk.cfg))) { SCLogError("Failed to create socket: %s", strerror(-ret)); SCMutexUnlock(&xsk_protect.queue_protect); SCReturnInt(TM_ECODE_FAILED); @@ -640,9 +639,9 @@ static TmEcode ReceiveAFXDPThreadInit(ThreadVars *tv, const void *initdata, void ptv->threads = afxdpconfig->threads; - /* Socket configuration */ + /* Socket configuration. No TX ring is created, AF_XDP capture is receive + * only, so tx_size is left at 0 and a NULL TX ring is passed at bind. */ ptv->xsk.cfg.rx_size = afxdpconfig->rx_ring_size; - ptv->xsk.cfg.tx_size = XSK_RING_PROD__DEFAULT_NUM_DESCS; ptv->xsk.cfg.xdp_flags = afxdpconfig->mode; ptv->xsk.cfg.bind_flags = afxdpconfig->bind_flags;