]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
netmap: Forward port packet stall fix 8677/head
authorJeff Lucovsky <jlucovsky@oisf.net>
Sat, 1 Apr 2023 13:47:56 +0000 (09:47 -0400)
committerVictor Julien <vjulien@oisf.net>
Mon, 3 Apr 2023 19:19:28 +0000 (21:19 +0200)
Issue: 5862

This commit forward ports fixes from master-6.0.x that address packet
stalling that may occur under IPS configurations.

src/runmode-netmap.c
src/source-netmap.c

index dd38735e5f53961e3a5d7f94d18ad2d425b08fdc..f5fbd6e4dbf3ce3fcfd85e3c6f16a5b9f7ad4cdb 100644 (file)
@@ -295,7 +295,7 @@ finalize:
     if (ns->threads_auto) {
         /* As NetmapGetRSSCount used to be broken on Linux,
          * fall back to GetIfaceRSSQueuesNum if needed. */
-        ns->threads = NetmapGetRSSCount(ns->iface);
+        ns->threads = NetmapGetRSSCount(base_name);
         if (ns->threads == 0) {
             /* need to use base_name of interface here */
             ns->threads = GetIfaceRSSQueuesNum(base_name);
@@ -377,15 +377,17 @@ static void *ParseNetmapConfig(const char *iface_name)
         LiveRegisterDevice(live_buf);
     }
 
+    /* we need the base interface name with any trailing software
+     * ring marker stripped for HW offloading checks */
+    char base_name[sizeof(aconf->in.iface)];
+    strlcpy(base_name, aconf->in.iface, sizeof(base_name));
+    /* for a sw_ring enabled device name, strip the trailing char */
+    if (aconf->in.sw_ring) {
+        base_name[strlen(base_name) - 1] = '\0';
+    }
+
     /* netmap needs all offloading to be disabled */
     if (aconf->in.real) {
-        char base_name[sizeof(aconf->in.iface)];
-        strlcpy(base_name, aconf->in.iface, sizeof(base_name));
-        /* for a sw_ring enabled device name, strip the trailing char */
-        if (aconf->in.sw_ring) {
-            base_name[strlen(base_name) - 1] = '\0';
-        }
-
         if (LiveGetOffload() == 0) {
             (void)GetIfaceOffloading(base_name, 1, 1);
         } else {
index 4e50889cd348b8f12577907f1564c55f44f4d6df..0b04b41b52d64af7edb6fec763aea7db74bcf518 100644 (file)
@@ -188,7 +188,7 @@ int NetmapGetRSSCount(const char *ifname)
         goto error_open;
     }
 
-    /* query netmap interface info */
+    /* query netmap interface info for ring count */
     memset(&req, 0, sizeof(req));
     memset(&hdr, 0, sizeof(hdr));
     hdr.nr_version = NETMAP_API;
@@ -197,7 +197,8 @@ int NetmapGetRSSCount(const char *ifname)
     strlcpy(hdr.nr_name, base_name, sizeof(hdr.nr_name));
 
     if (ioctl(fd, NIOCCTRL, &hdr) != 0) {
-        SCLogError("%s: failed to query netmap for device info: %s", ifname, strerror(errno));
+        SCLogError(
+                "Query of netmap HW rings count on %s failed; error: %s", ifname, strerror(errno));
         goto error_fd;
     };
 
@@ -613,8 +614,21 @@ static TmEcode NetmapWritePacket(NetmapThreadVars *ntv, Packet *p)
         SCMutexLock(&ntv->ifdst->netmap_dev_lock);
     }
 
+    int write_tries = 0;
+try_write:
     /* attempt to write the packet into the netmap ring buffer(s) */
     if (nmport_inject(ntv->ifdst->nmd, GET_PKT_DATA(p), GET_PKT_LEN(p)) == 0) {
+
+        /* writing the packet failed, but ask kernel to sync TX rings
+         * for us as the ring buffers may simply be full */
+        (void)ioctl(ntv->ifdst->nmd->fd, NIOCTXSYNC, 0);
+
+        /* Try write up to 2 more times before giving up */
+        if (write_tries < 3) {
+            write_tries++;
+            goto try_write;
+        }
+
         if (ntv->flags & NETMAP_FLAG_EXCL_RING_ACCESS) {
             SCMutexUnlock(&ntv->ifdst->netmap_dev_lock);
         }
@@ -627,7 +641,7 @@ static TmEcode NetmapWritePacket(NetmapThreadVars *ntv, Packet *p)
             ntv->ifdst->ifname, ntv->ifdst->ring, GET_PKT_LEN(p));
 
     /* Instruct netmap to push the data on the TX ring on the destination port */
-    ioctl(ntv->ifdst->nmd->fd, NIOCTXSYNC, 0);
+    (void)ioctl(ntv->ifdst->nmd->fd, NIOCTXSYNC, 0);
     if (ntv->flags & NETMAP_FLAG_EXCL_RING_ACCESS) {
         SCMutexUnlock(&ntv->ifdst->netmap_dev_lock);
     }