diff --git a/src/runmode-netmap.c b/src/runmode-netmap.c index 9e31b08b2..f645dec41 100644 --- a/src/runmode-netmap.c +++ b/src/runmode-netmap.c @@ -69,15 +69,13 @@ const char *RunModeNetmapGetDefaultMode(void) void RunModeIdsNetmapRegister(void) { -#if HAVE_NETMAP - SCLogInfo("Using netmap version %d [" +#ifdef HAVE_NETMAP #if USE_NEW_NETMAP_API - "new" + SCLogInfo("Using netmap API version %d with multiple host rings support", NETMAP_API); #else - "legacy" -#endif - " API interfaces]", - NETMAP_API); + SCLogInfo("Using netmap API version %d with single host ring support", NETMAP_API); +#endif /* USE_NEW_NETMAP_API */ +#endif /* HAVE_NETMAP */ RunModeRegisterNewRunMode(RUNMODE_NETMAP, "single", "Single threaded netmap mode", RunModeIdsNetmapSingle); @@ -91,7 +89,6 @@ void RunModeIdsNetmapRegister(void) "thread.", RunModeIdsNetmapAutoFp); return; -#endif } #ifdef HAVE_NETMAP @@ -127,13 +124,17 @@ static int ParseNetmapSettings(NetmapIfaceSettings *ns, const char *iface, } } +#if USE_NEW_NETMAP_API /* we will need the base interface name for later */ char base_name[IFNAMSIZ]; strlcpy(base_name, ns->iface, sizeof(base_name)); if (strlen(base_name) > 0 && - (base_name[strlen(base_name) - 1] == '^' || base_name[strlen(base_name) - 1] == '*')) { + (base_name[strlen(base_name) - 1] == '^' || base_name[strlen(base_name) - 1] == '*')) { base_name[strlen(base_name) - 1] = '\0'; } +#else + char *base_name = ns->iface; +#endif /* USE_NEW_NETMAP_API */ /* prefixed with netmap or vale means it's not a real interface * and we don't check offloading. */ @@ -237,7 +238,7 @@ finalize: /* just one thread per interface supported */ ns->threads = 1; } else { -#endif +#endif /* !USE_NEW_NETMAP_API */ if (ns->threads_auto) { /* As NetmapGetRSSCount used to be broken on Linux, * fall back to GetIfaceRSSQueuesNum if needed. */ @@ -249,7 +250,7 @@ finalize: } #if !USE_NEW_NETMAP_API } -#endif +#endif /* !USE_NEW_NETMAP_API */ if (ns->threads <= 0) { ns->threads = 1; } @@ -317,7 +318,7 @@ static void *ParseNetmapConfig(const char *iface_name) } else if (aconf->in.sw_ring && aconf->out.threads_auto) { aconf->out.threads = aconf->in.threads = 1; } -#endif +#endif /* !USE_NEW_NETMAP_API */ } } @@ -339,8 +340,8 @@ static void *ParseNetmapConfig(const char *iface_name) LiveRegisterDevice(live_buf); } -#endif - /* netmap needs all offloading to be disabled */ +#endif /* USE_NEW_NETMAP_API */ + /* netmap needs all offloading to be disabled on RX side */ if (aconf->in.real) { char base_name[sizeof(aconf->in.iface)]; strlcpy(base_name, aconf->in.iface, sizeof(base_name)); @@ -363,7 +364,7 @@ static void *ParseNetmapConfig(const char *iface_name) #if USE_NEW_NETMAP_API LiveDeviceHasNoStats(); -#endif +#endif /* USE_NEW_NETMAP_API */ return aconf; } @@ -453,7 +454,7 @@ int NetmapRunModeIsIPS() return has_ips; } -#endif // #ifdef HAVE_NETMAP +#endif /* HAVE_NETMAP */ int RunModeIdsNetmapAutoFp(void) { diff --git a/src/source-netmap.c b/src/source-netmap.c index 00b4400b4..ddbe50c4f 100644 --- a/src/source-netmap.c +++ b/src/source-netmap.c @@ -66,11 +66,13 @@ #define NETMAP_WITH_LIBS #ifdef DEBUG #define DEBUG_NETMAP_USER -#endif +#endif /* DEBUG */ + #include + #if USE_NEW_NETMAP_API #include -#endif +#endif /* USE_NEW_NETMAP_API */ #endif /* HAVE_NETMAP */ @@ -159,6 +161,7 @@ typedef struct NetmapThreadVars_ int flags; struct bpf_program bpf_prog; + struct nm_pkthdr pkt_hdr; /* suricata internals */ TmSlot *slot; @@ -187,18 +190,23 @@ static SCMutex netmap_devlist_lock = SCMUTEX_INITIALIZER; */ int NetmapGetRSSCount(const char *ifname) { +#if USE_NEW_NETMAP_API struct nmreq_port_info_get req; struct nmreq_header hdr; +#else + struct nmreq nm_req; +#endif int rx_rings = 0; - /* we need the base interface name to query queues */ +#if USE_NEW_NETMAP_API + /* we need the base interface name to query queues count */ char base_name[IFNAMSIZ]; strlcpy(base_name, ifname, sizeof(base_name)); if (strlen(base_name) > 0 && (base_name[strlen(base_name) - 1] == '^' || base_name[strlen(base_name) - 1] == '*')) { base_name[strlen(base_name) - 1] = '\0'; } - +#endif SCMutexLock(&netmap_devlist_lock); /* open netmap device */ @@ -211,23 +219,36 @@ int NetmapGetRSSCount(const char *ifname) } /* query netmap interface info */ +#if USE_NEW_NETMAP_API memset(&req, 0, sizeof(req)); memset(&hdr, 0, sizeof(hdr)); hdr.nr_version = NETMAP_API; hdr.nr_reqtype = NETMAP_REQ_PORT_INFO_GET; hdr.nr_body = (uintptr_t)&req; strlcpy(hdr.nr_name, base_name, sizeof(hdr.nr_name)); +#else + memset(&nm_req, 0, sizeof(nm_req)); + strlcpy(nm_req.nr_name, ifname, sizeof(nm_req.nr_name)); + nm_req.nr_version = NETMAP_API; +#endif +#if USE_NEW_NETMAP_API if (ioctl(fd, NIOCCTRL, &hdr) != 0) { +#else + if (ioctl(fd, NIOCGINFO, &nm_req) != 0) { +#endif SCLogError(SC_ERR_NETMAP_CREATE, "Couldn't query netmap for info about %s, error %s", ifname, strerror(errno)); goto error_fd; }; +#if USE_NEW_NETMAP_API /* return RX rings count if it equals TX rings count */ - if (req.nr_rx_rings == req.nr_tx_rings) { + if (req.nr_rx_rings == req.nr_tx_rings) rx_rings = req.nr_rx_rings; - } +#else + rx_rings = nm_req.nr_rx_rings; +#endif error_fd: close(fd); @@ -287,17 +308,14 @@ static void NetmapCloseAll(void) /** * \brief Open interface in netmap mode. - * \param ifname Interface name. - * \param promisc Enable promiscuous mode. + * \param ns Pointer to Netmap Interface conf settings. * \param dev Pointer to requested netmap device instance. - * \param verbose Verbose error logging. - * \param read Indicates direction: RX or TX - * \param zerocopy 1 if zerocopy access requested + * \param ntv Pointer to NetmapThreadVars structure. + * \param read Indicates direction: 1 = RX or 0 = TX * \param soft Use Host stack (software) interface * \return Zero on success. */ -static int NetmapOpen(NetmapIfaceSettings *ns, NetmapDevice **pdevice, int verbose, int read, - bool zerocopy, bool soft) +static int NetmapOpen(NetmapIfaceSettings *ns, NetmapDevice **pdevice, NetmapThreadVars *ntv, int read, bool soft) { SCEnter(); SCLogDebug("ifname %s", ns->iface); @@ -315,10 +333,8 @@ static int NetmapOpen(NetmapIfaceSettings *ns, NetmapDevice **pdevice, int verbo /* check interface is up */ int if_flags = GetIfaceFlags(base_name); if (if_flags == -1) { - if (verbose) { - SCLogError(SC_ERR_NETMAP_CREATE, "Cannot access network interface '%s' (%s)", - base_name, ns->iface); - } + SCLogError(SC_ERR_NETMAP_CREATE, "Cannot access network interface '%s' (%s) to query for option flags", + base_name, ns->iface); goto error; } @@ -390,7 +406,7 @@ static int NetmapOpen(NetmapIfaceSettings *ns, NetmapDevice **pdevice, int verbo * When using multiple rings/threads, then the open of the initial Ring 0 MUST * instruct netmap to open multiple Host Stack rings (as the default is to open only a single * pair). This is also critical for the HW NIC endpoint. This is done by adding - * “@conf:host-rings=x” suffix option (where “x” is the number of host rings desired) + * "@conf:host-rings=x" suffix option (where 'x' is the number of host rings desired) * to BOTH endpoint nmport_open_desc() calls for ring 0 (hardware and host stack). * For subsequent additional ring open calls, omit the suffix option specifying host ring count. * @@ -412,7 +428,7 @@ retry: ns->iface, ring, strlen(optstr) ? "/" : "", optstr); } else if (strlen(ns->iface) > 5 && strncmp(ns->iface, "vale", 4) == 0 && isdigit(ns->iface[4])) { snprintf(devname, sizeof(devname), "%s", ns->iface); -#if NETMAP_API < 14 || !USET_NET_NETMAP_API +#if NETMAP_API < 14 || !USE_NEW_NETMAP_API } else if (ns->iface[strlen(ns->iface)-1] == '*' || ns->iface[strlen(ns->iface)-1] == '^') { SCLogDebug("device with SW-ring enabled (ns->iface): %s",ns->iface); @@ -462,23 +478,7 @@ retry: strlcpy(pdev->ifname, ns->iface, sizeof(pdev->ifname)); #if USE_NEW_NETMAP_API - /* have the netmap API parse device name and prepare the port descriptor for us */ - pdev->nmd = nmport_prepare(devname); - - if (pdev->nmd != NULL) { - /* For RX devices, set the nr_mode flag we need on the netmap port TX rings prior to opening - */ - if (read) { - pdev->nmd->reg.nr_flags |= NR_NO_TX_POLL; - } - - /* Now attempt to actually open the netmap port descriptor */ - if (nmport_open_desc(pdev->nmd) < 0) { - /* the open failed, so clean-up the descriptor and fall through to error handler */ - nmport_close(pdev->nmd); - pdev->nmd = NULL; - } - } + pdev->nmd = nmport_open(devname); #else pdev->nmd = nm_open(devname, NULL, 0, NULL); #endif @@ -500,11 +500,13 @@ retry: FatalError(SC_ERR_FATAL, "opening devname %s failed: %s", devname, strerror(errno)); } +#if USE_NEW_NETMAP_API /* Work around bug in libnetmap library where "cur_{r,t}x_ring" values not initialized */ SCLogDebug("%s -- cur rings: [%d, %d] first rings: [%d, %d]", devname, pdev->nmd->cur_rx_ring, pdev->nmd->cur_tx_ring, pdev->nmd->first_rx_ring, pdev->nmd->first_tx_ring); pdev->nmd->cur_rx_ring = pdev->nmd->first_rx_ring; pdev->nmd->cur_tx_ring = pdev->nmd->first_tx_ring; +#endif SCLogInfo("devname [fd: %d] %s %s opened", pdev->nmd->fd, devname, ns->iface); @@ -577,17 +579,16 @@ static TmEcode ReceiveNetmapThreadInit(ThreadVars *tv, const void *initdata, voi ntv->flags |= NETMAP_FLAG_EXCL_RING_ACCESS; } - /* Need to insure open of ring 0 conveys requested ring count for open */ + /* set flag if either side of interface pair is host stack */ bool soft = aconf->in.sw_ring || aconf->out.sw_ring; - if (NetmapOpen(&aconf->in, &ntv->ifsrc, 1, 1, (ntv->flags & NETMAP_FLAG_ZERO_COPY) != 0, - soft) != 0) { + if (NetmapOpen(&aconf->in, &ntv->ifsrc, ntv, 1, soft) != 0) { goto error_ntv; } #if !USE_NEW_NETMAP_API if (unlikely(aconf->in.sw_ring && aconf->in.threads > 1)) { SCLogError(SC_ERR_INVALID_VALUE, - "Interface '%s^'. " + "Source Interface '%s^'. " "Thread count can't be greater than 1 for SW ring.", aconf->iface_name); goto error_src; @@ -595,9 +596,8 @@ static TmEcode ReceiveNetmapThreadInit(ThreadVars *tv, const void *initdata, voi #endif if (aconf->in.copy_mode != NETMAP_COPY_MODE_NONE) { - if (NetmapOpen(&aconf->out, &ntv->ifdst, 1, 0, (ntv->flags & NETMAP_FLAG_ZERO_COPY) != 0, - soft) != 0) { - goto error_src; + if (NetmapOpen(&aconf->out, &ntv->ifdst, ntv, 0, soft) != 0) { + goto error_dst; } } @@ -609,25 +609,27 @@ static TmEcode ReceiveNetmapThreadInit(ThreadVars *tv, const void *initdata, voi if (aconf->in.bpf_filter) { SCLogConfig("Using BPF '%s' on iface '%s'", - aconf->in.bpf_filter, ntv->ifsrc->ifname); + aconf->in.bpf_filter, ntv->ifsrc->ifname); char errbuf[PCAP_ERRBUF_SIZE]; if (SCBPFCompile(default_packet_size, /* snaplen_arg */ - LINKTYPE_ETHERNET, /* linktype_arg */ - &ntv->bpf_prog, /* program */ - aconf->in.bpf_filter, /* const char *buf */ - 1, /* optimize */ - PCAP_NETMASK_UNKNOWN, /* mask */ + LINKTYPE_ETHERNET, /* linktype_arg */ + &ntv->bpf_prog, /* program */ + aconf->in.bpf_filter, /* const char *buf */ + 1, /* optimize */ + PCAP_NETMASK_UNKNOWN, /* mask */ errbuf, sizeof(errbuf)) == -1) { SCLogError(SC_ERR_NETMAP_CREATE, "Failed to compile BPF \"%s\": %s", - aconf->in.bpf_filter, - errbuf); + aconf->in.bpf_filter, + errbuf); goto error_dst; } } - SCLogNotice("thread: %s polling on fd: %d", tv->name, ntv->ifsrc->nmd->fd); + int rx_rings = ntv->ifsrc->nmd->last_rx_ring - ntv->ifsrc->nmd->first_rx_ring + 1; + SCLogNotice("thread: %s polling on fd: %d using %d RX ring%s", tv->name, ntv->ifsrc->nmd->fd, + rx_rings, rx_rings == 1 ? "" : "s"); *data = (void *)ntv; aconf->DerefFunc(aconf); @@ -659,29 +661,38 @@ static TmEcode NetmapWritePacket(NetmapThreadVars *ntv, Packet *p) } DEBUG_VALIDATE_BUG_ON(ntv->ifdst == NULL); - /* Lock the destination netmap ring while writing to it */ + /* Lock destination netmap TX ring while writing when autofp runmode */ if (ntv->flags & NETMAP_FLAG_EXCL_RING_ACCESS) { SCMutexLock(&ntv->ifdst->netmap_dev_lock); } - /* attempt to write the packet into the netmap ring buffer(s) */ + /* write the Packet's data into available ring slot(s) */ #if USE_NEW_NETMAP_API if (nmport_inject(ntv->ifdst->nmd, GET_PKT_DATA(p), GET_PKT_LEN(p)) == 0) { - if (ntv->flags & NETMAP_FLAG_EXCL_RING_ACCESS) { - SCMutexUnlock(&ntv->ifdst->netmap_dev_lock); - } #else if (nm_inject(ntv->ifdst->nmd, GET_PKT_DATA(p), GET_PKT_LEN(p)) == 0) { #endif + /* an error occurred sending to netmap destination port, + * so release our mutex if used and log a dropped packet. + */ + if (ntv->flags & NETMAP_FLAG_EXCL_RING_ACCESS) { + SCMutexUnlock(&ntv->ifdst->netmap_dev_lock); + } SCLogDebug("failed to send %s -> %s", ntv->ifsrc->ifname, ntv->ifdst->ifname); ntv->drops++; return TM_ECODE_FAILED; } - SCLogDebug("sent successfully: %s(%d)->%s(%d) (%u)", ntv->ifsrc->ifname, ntv->ifsrc->ring, - ntv->ifdst->ifname, ntv->ifdst->ring, GET_PKT_LEN(p)); + /* Sync TX rings with kernel using NIOTXSYNC */ + if (ioctl(ntv->ifdst->nmd->fd, NIOCTXSYNC, 0) == -1) { + SCLogWarning(SC_ERR_SYSCALL, "An error occurred syncing TX ring #%d on %s.", + ntv->ifdst->ring, ntv->ifdst->ifname); + } else { + SCLogDebug("sent successfully: %s(%d)->%s(%d) (%u)", ntv->ifsrc->ifname, ntv->ifsrc->ring, + ntv->ifdst->ifname, ntv->ifdst->ring, GET_PKT_LEN(p)); + } - ioctl(ntv->ifdst->nmd->fd, NIOCTXSYNC, 0); + /* release netmap write mutex if runmode = autofp */ if (ntv->flags & NETMAP_FLAG_EXCL_RING_ACCESS) { SCMutexUnlock(&ntv->ifdst->netmap_dev_lock); } @@ -703,12 +714,13 @@ static void NetmapReleasePacket(Packet *p) PacketFreeOrRelease(p); } -static void NetmapProcessPacket(NetmapThreadVars *ntv, const struct nm_pkthdr *ph) +static void NetmapCallback(u_char *user, const struct nm_pkthdr *ph, const u_char *d) { + NetmapThreadVars *ntv = (NetmapThreadVars *)user; if (ntv->bpf_prog.bf_len) { struct pcap_pkthdr pkthdr = { {0, 0}, ph->len, ph->len }; - if (pcap_offline_filter(&ntv->bpf_prog, &pkthdr, ph->buf) == 0) { + if (pcap_offline_filter(&ntv->bpf_prog, &pkthdr, d) == 0) { return; } } @@ -726,12 +738,12 @@ static void NetmapProcessPacket(NetmapThreadVars *ntv, const struct nm_pkthdr *p ntv->bytes += ph->len; if (ntv->flags & NETMAP_FLAG_ZERO_COPY) { - if (PacketSetData(p, (uint8_t *)ph->buf, ph->len) == -1) { + if (PacketSetData(p, (uint8_t *)d, ph->len) == -1) { TmqhOutputPacketpool(ntv->tv, p); return; } } else { - if (PacketCopyData(p, (uint8_t *)ph->buf, ph->len) == -1) { + if (PacketCopyData(p, (uint8_t *)d, ph->len) == -1) { TmqhOutputPacketpool(ntv->tv, p); return; } @@ -748,33 +760,32 @@ static void NetmapProcessPacket(NetmapThreadVars *ntv, const struct nm_pkthdr *p /** * \brief Copy netmap rings data into Packet structures. - * \param *d nmport_d (or nm_desc) netmap if structure. + * \param *d nmport_d netmap port structure. * \param cnt int count of packets to read (-1 = all). * \param *ntv NetmapThreadVars. */ #if USE_NEW_NETMAP_API -static TmEcode NetmapReadPackets(struct nmport_d *d, int cnt, NetmapThreadVars *ntv) -#else -static TmEcode NetmapReadPackets(struct nm_desc *d, int cnt, NetmapThreadVars *ntv) -#endif +static int NetmapDispatchPackets(struct nmport_d *d, int cnt, NetmapThreadVars *ntv) { - struct nm_pkthdr hdr; - int last_ring = d->last_rx_ring - d->first_rx_ring + 1; - int cur_ring, got = 0, cur_rx_ring = d->cur_rx_ring; + int c, got = 0, ri = d->cur_rx_ring; - memset(&hdr, 0, sizeof(hdr)); - hdr.flags = NM_MORE_PKTS; + /* compute number of rings opened for this netmap port */ + int n = d->last_rx_ring - d->first_rx_ring + 1; + + ntv->pkt_hdr.buf = NULL; + ntv->pkt_hdr.flags = NM_MORE_PKTS; if (cnt == 0) cnt = -1; - for (cur_ring = 0; cur_ring < last_ring && cnt != got; cur_ring++, cur_rx_ring++) { + /* Loop through the rings in the netmap port */ + for (c = 0; c < n && cnt != got; c++, ri++) { struct netmap_ring *ring; - if (cur_rx_ring > d->last_rx_ring) - cur_rx_ring = d->first_rx_ring; + if (ri > d->last_rx_ring) + ri = d->first_rx_ring; - ring = NETMAP_RXRING(d->nifp, cur_rx_ring); + ring = NETMAP_RXRING(d->nifp, ri); /* cycle through the non-empty ring slots to fetch their data */ for (; !nm_ring_empty(ring) && cnt != got; got++) { @@ -782,50 +793,57 @@ static TmEcode NetmapReadPackets(struct nm_desc *d, int cnt, NetmapThreadVars *n u_char *oldbuf; struct netmap_slot *slot; - if (hdr.buf) { /* from previous round */ - NetmapProcessPacket(ntv, &hdr); + if (ntv->pkt_hdr.buf) { /* data from previous pass */ + NetmapCallback((u_char *)ntv, &ntv->pkt_hdr, ntv->pkt_hdr.buf); } i = ring->cur; slot = &ring->slot[i]; idx = slot->buf_idx; - d->cur_rx_ring = cur_rx_ring; - hdr.slot = slot; - oldbuf = hdr.buf = (u_char *)NETMAP_BUF(ring, idx); - hdr.len = hdr.caplen = slot->len; + d->cur_rx_ring = ri; + ntv->pkt_hdr.slot = slot; + oldbuf = ntv->pkt_hdr.buf = (u_char *)NETMAP_BUF(ring, idx); + ntv->pkt_hdr.len = ntv->pkt_hdr.caplen = slot->len; /* loop through the ring slots to get packet data */ while (slot->flags & NS_MOREFRAG) { - /* packet can be fragmented across multiple slots, */ - /* so loop until we find the slot with the flag */ - /* cleared, signalling the end of the packet data. */ + /* packet may be fragmented across multiple slots, + * so loop until we find a slot with the flag + * cleared, signalling the end of packet's data. + */ u_char *nbuf; u_int oldlen = slot->len; - i = nm_ring_next(ring, i); + i = nm_ring_next(ring, i); /* advance to next slot */ slot = &ring->slot[i]; - hdr.len += slot->len; + ntv->pkt_hdr.len += slot->len; nbuf = (u_char *)NETMAP_BUF(ring, slot->buf_idx); if (oldbuf != NULL && nbuf - oldbuf == ring->nr_buf_size && oldlen == ring->nr_buf_size) { - hdr.caplen += slot->len; + ntv->pkt_hdr.caplen += slot->len; oldbuf = nbuf; } else { oldbuf = NULL; } } - hdr.ts = ring->ts; + ntv->pkt_hdr.ts = ring->ts; + + /* update cur & head so kernel knows we read the data on ring */ ring->head = ring->cur = nm_ring_next(ring, i); } } - if (hdr.buf) { /* from previous round */ - hdr.flags = 0; - NetmapProcessPacket(ntv, &hdr); + /* finished checking all the rings, copy any remaining data */ + if (ntv->pkt_hdr.buf) { + ntv->pkt_hdr.flags = 0; + NetmapCallback((u_char *)ntv, &ntv->pkt_hdr, ntv->pkt_hdr.buf); } + + /* return the count of Packet structs we filled */ return got; } +#endif /** * \brief Main netmap reading loop function @@ -849,7 +867,8 @@ static TmEcode ReceiveNetmapLoop(ThreadVars *tv, void *data, void *slot) } /* make sure we have at least one packet in the packet pool, - * to prevent us from alloc'ing packets at line rate */ + * to prevent us from alloc'ing packets at line rate + */ PacketPoolWait(); int r = poll(&fds, 1, POLL_TIMEOUT); @@ -862,10 +881,6 @@ static TmEcode ReceiveNetmapLoop(ThreadVars *tv, void *data, void *slot) continue; } else if (r == 0) { - /* no events, timeout */ - // SCLogDebug("(%s:%d-%d) Poll timeout", ntv->ifsrc->ifname, - // ntv->src_ring_from, ntv->src_ring_to); - /* sync counters */ NetmapDumpCounters(ntv); StatsSyncCountersIfSignalled(tv); @@ -880,9 +895,6 @@ static TmEcode ReceiveNetmapLoop(ThreadVars *tv, void *data, void *slot) SCLogError(SC_ERR_NETMAP_READ, "Error reading netmap data via polling from iface '%s': (%d" PRIu32 ") %s", ntv->ifsrc->ifname, errno, strerror(errno)); - // SCLogError(SC_ERR_NETMAP_READ, - // "Error reading data from iface '%s': (%d" PRIu32 ") %s", - // ntv->ifsrc->ifname, errno, strerror(errno)); } else if (fds.revents & POLLNVAL) { SCLogError(SC_ERR_NETMAP_READ, "Invalid polling request"); } @@ -890,8 +902,12 @@ static TmEcode ReceiveNetmapLoop(ThreadVars *tv, void *data, void *slot) } if (likely(fds.revents & POLLIN)) { - /* have data on RX ring, so copy to Packet for processing */ - NetmapReadPackets(ntv->ifsrc->nmd, -1, ntv); +#if USE_NEW_NETMAP_API + /* have RX rings data, so copy into Packet structs for analysis */ + NetmapDispatchPackets(ntv->ifsrc->nmd, -1, ntv); +#else + nm_dispatch(ntv->ifsrc->nmd, -1, NetmapCallback, (void *)ntv); +#endif } NetmapDumpCounters(ntv);