From: Jeff Lucovsky Date: Sat, 1 Apr 2023 13:47:56 +0000 (-0400) Subject: netmap: Forward port packet stall fix X-Git-Tag: suricata-7.0.0-rc2~452 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=035863d029290c864388577e7cc9e31250f98523;p=thirdparty%2Fsuricata.git netmap: Forward port packet stall fix Issue: 5862 This commit forward ports fixes from master-6.0.x that address packet stalling that may occur under IPS configurations. --- diff --git a/src/runmode-netmap.c b/src/runmode-netmap.c index dd38735e5f..f5fbd6e4db 100644 --- a/src/runmode-netmap.c +++ b/src/runmode-netmap.c @@ -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 { diff --git a/src/source-netmap.c b/src/source-netmap.c index 4e50889cd3..0b04b41b52 100644 --- a/src/source-netmap.c +++ b/src/source-netmap.c @@ -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); }