Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Netmap v4 #2134

Merged
merged 5 commits into from
Jun 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 26 additions & 19 deletions src/runmode-netmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ static void *ParseNetmapConfig(const char *iface_name)

memset(aconf, 0, sizeof(*aconf));
aconf->DerefFunc = NetmapDerefConfig;
aconf->threads = 1;
aconf->threads = 0;
aconf->promisc = 1;
aconf->checksum_mode = CHECKSUM_VALIDATION_AUTO;
aconf->copy_mode = NETMAP_COPY_MODE_NONE;
Expand Down Expand Up @@ -156,7 +156,7 @@ static void *ParseNetmapConfig(const char *iface_name)
netmap_node = ConfGetNode("netmap");
if (netmap_node == NULL) {
SCLogInfo("Unable to find netmap config using default value");
return aconf;
goto finalize;
}

if_root = ConfFindDeviceConfig(netmap_node, aconf->iface_name);
Expand All @@ -167,7 +167,7 @@ static void *ParseNetmapConfig(const char *iface_name)
SCLogInfo("Unable to find netmap config for "
"interface \"%s\" or \"default\", using default value",
aconf->iface_name);
return aconf;
goto finalize;
}

/* If there is no setting for current interface use default one as main iface */
Expand All @@ -177,23 +177,15 @@ static void *ParseNetmapConfig(const char *iface_name)
}

if (ConfGetChildValueWithDefault(if_root, if_default, "threads", &threadsstr) != 1) {
aconf->threads = 1;
aconf->threads = 0;
} else {
if (strcmp(threadsstr, "auto") == 0) {
aconf->threads = GetIfaceRSSQueuesNum(aconf->iface);
aconf->threads = 0;
} else {
aconf->threads = (uint8_t)atoi(threadsstr);
}
}

if (aconf->threads <= 0) {
aconf->threads = 1;
}
if (aconf->threads) {
SCLogInfo("Using %d threads for interface %s", aconf->threads,
aconf->iface_name);
}

if (ConfGetChildValueWithDefault(if_root, if_default, "copy-iface", &out_iface) == 1) {
if (strlen(out_iface) > 0) {
aconf->out_iface_name = out_iface;
Expand Down Expand Up @@ -231,9 +223,6 @@ static void *ParseNetmapConfig(const char *iface_name)
}
}

SC_ATOMIC_RESET(aconf->ref);
(void) SC_ATOMIC_ADD(aconf->ref, aconf->threads);

/* load netmap bpf filter */
/* command line value has precedence */
if (ConfGet("bpf-filter", &bpf_filter) != 1) {
Expand Down Expand Up @@ -263,6 +252,24 @@ static void *ParseNetmapConfig(const char *iface_name)
}
}

finalize:

if (aconf->threads == 0) {
/* As NetmapGetRSSCount is broken on Linux, first run
* GetIfaceRSSQueuesNum. If that fails, run NetmapGetRSSCount */
aconf->threads = GetIfaceRSSQueuesNum(aconf->iface);
if (aconf->threads == 0) {
aconf->threads = NetmapGetRSSCount(aconf->iface);
}
}
if (aconf->threads <= 0) {
aconf->threads = 1;
}
SC_ATOMIC_RESET(aconf->ref);
(void) SC_ATOMIC_ADD(aconf->ref, aconf->threads);
SCLogInfo("Using %d threads for interface %s", aconf->threads,
aconf->iface_name);

return aconf;
}

Expand Down Expand Up @@ -379,7 +386,7 @@ int RunModeIdsNetmapAutoFp(void)
exit(EXIT_FAILURE);
}

SCLogInfo("RunModeIdsNetmapAutoFp initialised");
SCLogDebug("RunModeIdsNetmapAutoFp initialised");
#endif /* HAVE_NETMAP */

SCReturnInt(0);
Expand Down Expand Up @@ -412,7 +419,7 @@ int RunModeIdsNetmapSingle(void)
exit(EXIT_FAILURE);
}

SCLogInfo("RunModeIdsNetmapSingle initialised");
SCLogDebug("RunModeIdsNetmapSingle initialised");

#endif /* HAVE_NETMAP */
SCReturnInt(0);
Expand Down Expand Up @@ -448,7 +455,7 @@ int RunModeIdsNetmapWorkers(void)
exit(EXIT_FAILURE);
}

SCLogInfo("RunModeIdsNetmapWorkers initialised");
SCLogDebug("RunModeIdsNetmapWorkers initialised");

#endif /* HAVE_NETMAP */
SCReturnInt(0);
Expand Down
91 changes: 91 additions & 0 deletions src/source-netmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,55 @@ static int NetmapGetIfaceFlags(int fd, const char *ifname)
#endif
}

#ifdef SIOCGIFCAP
static int NetmapGetIfaceCaps(int fd, const char *ifname)
{
struct ifreq ifr;

memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));

if (ioctl(fd, SIOCGIFCAP, &ifr) == -1) {
SCLogError(SC_ERR_NETMAP_CREATE,
"Unable to get caps for iface \"%s\": %s",
ifname, strerror(errno));
return -1;
}

return ifr.ifr_curcap;
}
#endif

static void NetmapCheckOffloading(int fd, const char *ifname)
{
#ifdef SIOCGIFCAP
int if_caps = NetmapGetIfaceCaps(fd, ifname);
if (if_caps == -1) {
return;
}
SCLogDebug("if_caps %X", if_caps);

if (if_caps & IFCAP_RXCSUM) {
SCLogWarning(SC_ERR_NETMAP_CREATE,
"Using NETMAP with RXCSUM activated can lead to capture "
"problems: ifconfig %s -rxcsum", ifname);
}
if (if_caps & (IFCAP_TSO|IFCAP_TOE|IFCAP_LRO)) {
SCLogWarning(SC_ERR_NETMAP_CREATE,
"Using NETMAP with TSO, TOE or LRO activated can lead to "
"capture problems: ifconfig %s -tso -toe -lro", ifname);
}
#else
if (GetIfaceOffloading(ifname) == 1) {
SCLogWarning(SC_ERR_NETMAP_CREATE,
"Using NETMAP with GRO or LRO activated can lead to "
"capture problems: "
"ethtool -K %s rx off sg off gro off gso off tso off",
ifname);
}
#endif
}

/**
* \brief Set interface flags.
* \param fd Network susbystem file descritor.
Expand Down Expand Up @@ -277,6 +326,46 @@ static int NetmapSetIfaceFlags(int fd, const char *ifname, int flags)
return 0;
}

/** \brief get RSS RX-queue count
* \retval rx_rings RSS RX queue count or 1 on error
*/
int NetmapGetRSSCount(const char *ifname)
{
struct nmreq nm_req;
int rx_rings = 1;

SCMutexLock(&netmap_devlist_lock);

/* open netmap */
int fd = open("/dev/netmap", O_RDWR);
if (fd == -1) {
SCLogError(SC_ERR_NETMAP_CREATE,
"Couldn't open netmap device, error %s",
strerror(errno));
goto error_open;
}

/* query netmap info */
memset(&nm_req, 0, sizeof(nm_req));
strlcpy(nm_req.nr_name, ifname, sizeof(nm_req.nr_name));
nm_req.nr_version = NETMAP_API;

if (ioctl(fd, NIOCGINFO, &nm_req) != 0) {
SCLogError(SC_ERR_NETMAP_CREATE,
"Couldn't query netmap for %s, error %s",
ifname, strerror(errno));
goto error_fd;
};

rx_rings = nm_req.nr_rx_rings;

error_fd:
close(fd);
error_open:
SCMutexUnlock(&netmap_devlist_lock);
return rx_rings;
}

/**
* \brief Open interface in netmap mode.
* \param ifname Interface name.
Expand Down Expand Up @@ -353,6 +442,8 @@ static int NetmapOpen(char *ifname, int promisc, NetmapDevice **pdevice, int ver
if_flags |= IFF_PROMISC;
NetmapSetIfaceFlags(if_fd, ifname, if_flags);
}

NetmapCheckOffloading(if_fd, ifname);
close(if_fd);

/* query netmap info */
Expand Down
2 changes: 2 additions & 0 deletions src/source-netmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ typedef struct NetmapPacketVars_
void *ntv;
} NetmapPacketVars;

int NetmapGetRSSCount(const char *ifname);

void TmModuleReceiveNetmapRegister (void);
void TmModuleDecodeNetmapRegister (void);

Expand Down
2 changes: 1 addition & 1 deletion suricata.yaml.in
Original file line number Diff line number Diff line change
Expand Up @@ -1445,7 +1445,7 @@ netmap:
# To specify OS endpoint add plus sign at the end (e.g. "eth0+")
- interface: eth2
# Number of receive threads. "auto" uses number of RSS queues on interface.
threads: auto
#threads: auto
# You can use the following variables to activate netmap tap or IPS mode.
# If copy-mode is set to ips or tap, the traffic coming to the current
# interface will be copied to the copy-iface interface. If 'tap' is set, the
Expand Down