]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
netmap: redo config parsing
authorVictor Julien <victor@inliniac.net>
Sat, 11 Jun 2016 11:30:16 +0000 (11:30 +0000)
committerVictor Julien <victor@inliniac.net>
Mon, 20 Jun 2016 15:57:59 +0000 (17:57 +0200)
Normally we parse the config per interface only. But to properly
setup the bridge, netmap also needs the config of it's peering
interface. Instead of using a complicated peering scheme like in
afpacket, simply parse the peers config too.

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

index e476dd04033e65879a56ec40dc206cd469f2ae27..81c409c2835eddfbc139257f2cf5a4bb91cbe18a 100644 (file)
@@ -93,183 +93,178 @@ static void NetmapDerefConfig(void *conf)
     }
 }
 
-/**
-* \brief extract information from config file
-*
-* The returned structure will be freed by the thread init function.
-* This is thus necessary to or copy the structure before giving it
-* to thread or to reparse the file for each thread (and thus have
-* new structure.
-*
-* \return a NetmapIfaceConfig corresponding to the interface name
-*/
-static void *ParseNetmapConfig(const char *iface_name)
+static int ParseNetmapSettings(NetmapIfaceSettings *ns, const char *iface,
+        ConfNode *if_root, ConfNode *if_default)
 {
-    char *threadsstr = NULL;
-    ConfNode *if_root;
-    ConfNode *if_default = NULL;
-    ConfNode *netmap_node;
-    char *tmpctype;
-    char *copymodestr;
-    int boolval;
-    char *bpf_filter = NULL;
-    char *out_iface = NULL;
-
-    if (iface_name == NULL) {
-        return NULL;
-    }
-
-    NetmapIfaceConfig *aconf = SCMalloc(sizeof(*aconf));
-    if (unlikely(aconf == NULL)) {
-        return NULL;
-    }
-
-    memset(aconf, 0, sizeof(*aconf));
-    aconf->DerefFunc = NetmapDerefConfig;
-    aconf->threads = 0;
-    aconf->promisc = 1;
-    aconf->checksum_mode = CHECKSUM_VALIDATION_AUTO;
-    aconf->copy_mode = NETMAP_COPY_MODE_NONE;
-    strlcpy(aconf->iface_name, iface_name, sizeof(aconf->iface_name));
-    SC_ATOMIC_INIT(aconf->ref);
-    (void) SC_ATOMIC_ADD(aconf->ref, 1);
-
-    strlcpy(aconf->iface, aconf->iface_name, sizeof(aconf->iface));
-    if (aconf->iface[0]) {
-        size_t len = strlen(aconf->iface);
-        if (aconf->iface[len-1] == '+') {
-            aconf->iface[len-1] = '\0';
-            aconf->iface_sw = 1;
+    ns->threads = 0;
+    ns->promisc = 1;
+    ns->checksum_mode = CHECKSUM_VALIDATION_AUTO;
+    ns->copy_mode = NETMAP_COPY_MODE_NONE;
+
+    strlcpy(ns->iface, iface, sizeof(ns->iface));
+    if (ns->iface[0]) {
+        size_t len = strlen(ns->iface);
+        if (ns->iface[len-1] == '+') {
+            ns->iface[len-1] = '\0';
+            ns->sw_ring = 1;
         }
     }
 
+    char *bpf_filter = NULL;
     if (ConfGet("bpf-filter", &bpf_filter) == 1) {
         if (strlen(bpf_filter) > 0) {
-            aconf->bpf_filter = bpf_filter;
+            ns->bpf_filter = bpf_filter;
             SCLogInfo("Going to use command-line provided bpf filter '%s'",
-                    aconf->bpf_filter);
+                    ns->bpf_filter);
         }
     }
 
-    /* Find initial node */
-    netmap_node = ConfGetNode("netmap");
-    if (netmap_node == NULL) {
-        SCLogInfo("Unable to find netmap config using default value");
-        goto finalize;
-    }
-
-    if_root = ConfFindDeviceConfig(netmap_node, aconf->iface_name);
-
-    if_default = ConfFindDeviceConfig(netmap_node, "default");
-
     if (if_root == NULL && if_default == NULL) {
         SCLogInfo("Unable to find netmap config for "
-                "interface \"%s\" or \"default\", using default value",
-                aconf->iface_name);
+                "interface \"%s\" or \"default\", using default values",
+                iface);
         goto finalize;
-    }
 
     /* If there is no setting for current interface use default one as main iface */
-    if (if_root == NULL) {
+    } else if (if_root == NULL) {
         if_root = if_default;
         if_default = NULL;
     }
 
+    char *threadsstr = NULL;
     if (ConfGetChildValueWithDefault(if_root, if_default, "threads", &threadsstr) != 1) {
-        aconf->threads = 0;
+        ns->threads = 0;
     } else {
         if (strcmp(threadsstr, "auto") == 0) {
-            aconf->threads = 0;
-        } else {
-            aconf->threads = (uint8_t)atoi(threadsstr);
-        }
-    }
-
-    if (ConfGetChildValueWithDefault(if_root, if_default, "copy-iface", &out_iface) == 1) {
-        if (strlen(out_iface) > 0) {
-            aconf->out_iface_name = out_iface;
-        }
-    }
-
-    if (ConfGetChildValueWithDefault(if_root, if_default, "copy-mode", &copymodestr) == 1) {
-        if (aconf->out_iface_name == NULL) {
-            SCLogInfo("Copy mode activated but no destination"
-                    " iface. Disabling feature");
-        } else if (strlen(copymodestr) <= 0) {
-            aconf->out_iface_name = NULL;
-        } else if (strcmp(copymodestr, "ips") == 0) {
-            SCLogInfo("Netmap IPS mode activated %s->%s",
-                    aconf->iface_name,
-                    aconf->out_iface_name);
-            aconf->copy_mode = NETMAP_COPY_MODE_IPS;
-        } else if (strcmp(copymodestr, "tap") == 0) {
-            SCLogInfo("Netmap TAP mode activated %s->%s",
-                    aconf->iface_name,
-                    aconf->out_iface_name);
-            aconf->copy_mode = NETMAP_COPY_MODE_TAP;
+            ns->threads = 0;
         } else {
-            SCLogInfo("Invalid mode (not in tap, ips)");
-        }
-    }
-
-    if (aconf->out_iface_name && aconf->out_iface_name[0]) {
-        strlcpy(aconf->out_iface, aconf->out_iface_name,
-                sizeof(aconf->out_iface));
-        size_t len = strlen(aconf->out_iface);
-        if (aconf->out_iface[len-1] == '+') {
-            aconf->out_iface[len-1] = '\0';
-            aconf->out_iface_sw = 1;
+            ns->threads = (uint8_t)atoi(threadsstr);
         }
     }
 
     /* load netmap bpf filter */
     /* command line value has precedence */
-    if (ConfGet("bpf-filter", &bpf_filter) != 1) {
+    if (ns->bpf_filter == NULL) {
         if (ConfGetChildValueWithDefault(if_root, if_default, "bpf-filter", &bpf_filter) == 1) {
             if (strlen(bpf_filter) > 0) {
-                aconf->bpf_filter = bpf_filter;
-                SCLogInfo("Going to use bpf filter %s", aconf->bpf_filter);
+                ns->bpf_filter = bpf_filter;
+                SCLogInfo("Going to use bpf filter %s", ns->bpf_filter);
             }
         }
     }
 
+    int boolval = 0;
     (void)ConfGetChildValueBoolWithDefault(if_root, if_default, "disable-promisc", (int *)&boolval);
     if (boolval) {
-        SCLogInfo("Disabling promiscuous mode on iface %s", aconf->iface);
-        aconf->promisc = 0;
+        SCLogInfo("Disabling promiscuous mode on iface %s", ns->iface);
+        ns->promisc = 0;
     }
 
-    if (ConfGetChildValueWithDefault(if_root, if_default, "checksum-checks", &tmpctype) == 1) {
+    char *tmpctype;
+    if (ConfGetChildValueWithDefault(if_root, if_default,
+                "checksum-checks", &tmpctype) == 1)
+    {
         if (strcmp(tmpctype, "auto") == 0) {
-            aconf->checksum_mode = CHECKSUM_VALIDATION_AUTO;
+            ns->checksum_mode = CHECKSUM_VALIDATION_AUTO;
         } else if (ConfValIsTrue(tmpctype)) {
-            aconf->checksum_mode = CHECKSUM_VALIDATION_ENABLE;
+            ns->checksum_mode = CHECKSUM_VALIDATION_ENABLE;
         } else if (ConfValIsFalse(tmpctype)) {
-            aconf->checksum_mode = CHECKSUM_VALIDATION_DISABLE;
+            ns->checksum_mode = CHECKSUM_VALIDATION_DISABLE;
         } else {
-            SCLogError(SC_ERR_INVALID_ARGUMENT, "Invalid value for checksum-checks for %s", aconf->iface_name);
+            SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Invalid value for "
+                    "checksum-checks for %s", iface);
+        }
+    }
+
+    char *copymodestr;
+    if (ConfGetChildValueWithDefault(if_root, if_default,
+                "copy-mode", &copymodestr) == 1)
+    {
+        if (strcmp(copymodestr, "ips") == 0) {
+            ns->copy_mode = NETMAP_COPY_MODE_IPS;
+        } else if (strcmp(copymodestr, "tap") == 0) {
+            ns->copy_mode = NETMAP_COPY_MODE_TAP;
+        } else {
+            SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Invalid copy-mode "
+                    "(valid are tap, ips)");
         }
     }
 
 finalize:
 
-    if (aconf->iface_sw) {
+    if (ns->sw_ring) {
         /* just one thread per interface supported */
-        aconf->threads = 1;
-    } else if (aconf->threads == 0) {
+        ns->threads = 1;
+    } else if (ns->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);
+        ns->threads = GetIfaceRSSQueuesNum(ns->iface);
+        if (ns->threads == 0) {
+            ns->threads = NetmapGetRSSCount(ns->iface);
         }
     }
-    if (aconf->threads <= 0) {
-        aconf->threads = 1;
+    if (ns->threads <= 0) {
+        ns->threads = 1;
     }
+
+    return 0;
+}
+
+/**
+* \brief extract information from config file
+*
+* The returned structure will be freed by the thread init function.
+* This is thus necessary to or copy the structure before giving it
+* to thread or to reparse the file for each thread (and thus have
+* new structure.
+*
+* \return a NetmapIfaceConfig corresponding to the interface name
+*/
+static void *ParseNetmapConfig(const char *iface_name)
+{
+    ConfNode *if_root = NULL;
+    ConfNode *if_default = NULL;
+    ConfNode *netmap_node;
+    char *out_iface = NULL;
+
+    if (iface_name == NULL) {
+        return NULL;
+    }
+
+    NetmapIfaceConfig *aconf = SCMalloc(sizeof(*aconf));
+    if (unlikely(aconf == NULL)) {
+        return NULL;
+    }
+
+    memset(aconf, 0, sizeof(*aconf));
+    aconf->DerefFunc = NetmapDerefConfig;
+    strlcpy(aconf->iface_name, iface_name, sizeof(aconf->iface_name));
+    SC_ATOMIC_INIT(aconf->ref);
+    (void) SC_ATOMIC_ADD(aconf->ref, 1);
+
+    /* Find initial node */
+    netmap_node = ConfGetNode("netmap");
+    if (netmap_node == NULL) {
+        SCLogInfo("Unable to find netmap config using default value");
+    } else {
+        if_root = ConfFindDeviceConfig(netmap_node, aconf->iface_name);
+        if_default = ConfFindDeviceConfig(netmap_node, "default");
+    }
+
+    /* parse settings for capture iface */
+    ParseNetmapSettings(&aconf->in, aconf->iface_name, if_root, if_default);
+
+    /* if we have a copy iface, parse that as well */
+    if (ConfGetChildValueWithDefault(if_root, if_default, "copy-iface", &out_iface) == 1) {
+        if (strlen(out_iface) > 0) {
+            if_root = ConfFindDeviceConfig(netmap_node, out_iface);
+            ParseNetmapSettings(&aconf->out, out_iface, if_root, if_default);
+        }
+    }
+
     SC_ATOMIC_RESET(aconf->ref);
-    (void) SC_ATOMIC_ADD(aconf->ref, aconf->threads);
-    SCLogPerf("Using %d threads for interface %s", aconf->threads,
+    (void) SC_ATOMIC_ADD(aconf->ref, aconf->in.threads);
+    SCLogPerf("Using %d threads for interface %s", aconf->in.threads,
             aconf->iface_name);
 
     return aconf;
@@ -278,7 +273,7 @@ finalize:
 static int NetmapConfigGeThreadsCount(void *conf)
 {
     NetmapIfaceConfig *aconf = (NetmapIfaceConfig *)conf;
-    return aconf->threads;
+    return aconf->in.threads;
 }
 
 int NetmapRunModeIsIPS()
index d9223fe653e039749734bc79db52b2a383d2d776..b9ce7a843f9474e4e029ca581234da3b6608b75a 100644 (file)
@@ -622,8 +622,8 @@ static TmEcode ReceiveNetmapThreadInit(ThreadVars *tv, void *initdata, void **da
     memset(ntv, 0, sizeof(*ntv));
 
     ntv->tv = tv;
-    ntv->checksum_mode = aconf->checksum_mode;
-    ntv->copy_mode = aconf->copy_mode;
+    ntv->checksum_mode = aconf->in.checksum_mode;
+    ntv->copy_mode = aconf->in.copy_mode;
 
     ntv->livedev = LiveGetDevice(aconf->iface_name);
     if (ntv->livedev == NULL) {
@@ -631,32 +631,32 @@ static TmEcode ReceiveNetmapThreadInit(ThreadVars *tv, void *initdata, void **da
         goto error_ntv;
     }
 
-    if (NetmapOpen(aconf->iface, aconf->promisc, &ntv->ifsrc, 1) != 0) {
+    if (NetmapOpen(aconf->in.iface, aconf->in.promisc, &ntv->ifsrc, 1) != 0) {
         goto error_ntv;
     }
 
-    if (unlikely(!aconf->iface_sw && !ntv->ifsrc->rx_rings_cnt)) {
+    if (unlikely(!aconf->in.sw_ring && !ntv->ifsrc->rx_rings_cnt)) {
         SCLogError(SC_ERR_NETMAP_CREATE,
                    "Input interface '%s' does not have Rx rings",
                    aconf->iface_name);
         goto error_src;
     }
 
-    if (unlikely(aconf->iface_sw && aconf->threads > 1)) {
+    if (unlikely(aconf->in.sw_ring && aconf->in.threads > 1)) {
         SCLogError(SC_ERR_INVALID_VALUE,
                    "Interface '%s+'. "
                    "Thread count can't be greater than 1 for SW ring.",
                    aconf->iface_name);
         goto error_src;
-    } else if (unlikely(aconf->threads > ntv->ifsrc->rx_rings_cnt)) {
+    } else if (unlikely(aconf->in.threads > ntv->ifsrc->rx_rings_cnt)) {
         SCLogError(SC_ERR_INVALID_VALUE,
                    "Thread count can't be greater than Rx ring count. "
                    "Configured %d threads for interface '%s' with %d Rx rings.",
-                   aconf->threads, aconf->iface_name, ntv->ifsrc->rx_rings_cnt);
+                   aconf->in.threads, aconf->iface_name, ntv->ifsrc->rx_rings_cnt);
         goto error_src;
     }
 
-    if (aconf->iface_sw) {
+    if (aconf->in.sw_ring) {
         ntv->thread_idx = 0;
     } else {
         do {
@@ -665,35 +665,35 @@ static TmEcode ReceiveNetmapThreadInit(ThreadVars *tv, void *initdata, void **da
     }
 
     /* calculate thread rings binding */
-    if (aconf->iface_sw) {
+    if (aconf->in.sw_ring) {
         ntv->src_ring_from = ntv->src_ring_to = ntv->ifsrc->rings_cnt;
     } else {
-        int tmp = (ntv->ifsrc->rx_rings_cnt + 1) / aconf->threads;
+        int tmp = (ntv->ifsrc->rx_rings_cnt + 1) / aconf->in.threads;
         ntv->src_ring_from = ntv->thread_idx * tmp;
         ntv->src_ring_to = ntv->src_ring_from + tmp - 1;
-        if (ntv->thread_idx == (aconf->threads - 1)) {
+        if (ntv->thread_idx == (aconf->in.threads - 1)) {
             ntv->src_ring_to = ntv->ifsrc->rx_rings_cnt - 1;
         }
     }
     SCLogDebug("netmap: %s thread:%d rings:%d-%d", aconf->iface_name,
                ntv->thread_idx, ntv->src_ring_from, ntv->src_ring_to);
 
-    if (aconf->copy_mode != NETMAP_COPY_MODE_NONE) {
-        if (NetmapOpen(aconf->out_iface, 0, &ntv->ifdst, 1) != 0) {
+    if (aconf->in.copy_mode != NETMAP_COPY_MODE_NONE) {
+        if (NetmapOpen(aconf->out.iface, aconf->out.promisc, &ntv->ifdst, 1) != 0) {
             goto error_src;
         }
 
-        if (unlikely(!aconf->out_iface_sw && !ntv->ifdst->tx_rings_cnt)) {
+        if (unlikely(!aconf->out.sw_ring && !ntv->ifdst->tx_rings_cnt)) {
             SCLogError(SC_ERR_NETMAP_CREATE,
                        "Output interface '%s' does not have Tx rings",
-                       aconf->out_iface_name);
+                       aconf->out.iface);
             goto error_dst;
         }
 
         /* calculate dst rings bindings */
         for (int i = ntv->src_ring_from; i <= ntv->src_ring_to; i++) {
             NetmapRing *ring = &ntv->ifsrc->rings[i];
-            if (aconf->out_iface_sw) {
+            if (aconf->out.sw_ring) {
                 ring->dst_ring_from = ring->dst_ring_to = ntv->ifdst->rings_cnt;
             } else if (ntv->ifdst->tx_rings_cnt > ntv->ifsrc->rx_rings_cnt) {
                 int tmp = (ntv->ifdst->tx_rings_cnt + 1) / ntv->ifsrc->rx_rings_cnt;
@@ -709,7 +709,7 @@ static TmEcode ReceiveNetmapThreadInit(ThreadVars *tv, void *initdata, void **da
             ring->dst_next_ring = ring->dst_ring_from;
 
             SCLogDebug("netmap: %s(%d)->%s(%d-%d)",
-                       aconf->iface_name, i, aconf->out_iface_name,
+                       aconf->in.iface, i, aconf->out.iface,
                        ring->dst_ring_from, ring->dst_ring_to);
         }
     }
@@ -722,11 +722,11 @@ static TmEcode ReceiveNetmapThreadInit(ThreadVars *tv, void *initdata, void **da
 
     /* enable zero-copy mode for workers runmode */
     char const *active_runmode = RunmodeGetActive();
-    if ((aconf->copy_mode != NETMAP_COPY_MODE_NONE) && active_runmode
-            && !strcmp("workers", active_runmode)) {
+    if ((aconf->in.copy_mode != NETMAP_COPY_MODE_NONE) && active_runmode &&
+            strcmp("workers", active_runmode) == 0) {
         ntv->flags |= NETMAP_FLAG_ZERO_COPY;
         SCLogPerf("Enabling zero copy mode for %s->%s",
-                  aconf->iface_name, aconf->out_iface_name);
+                  aconf->in.iface, aconf->out.iface);
     } else {
         uint16_t ring_size = ntv->ifsrc->rings[0].rx->num_slots;
         if (ring_size > max_pending_packets) {
@@ -738,16 +738,17 @@ static TmEcode ReceiveNetmapThreadInit(ThreadVars *tv, void *initdata, void **da
         }
     }
 
-    if (aconf->bpf_filter) {
+    if (aconf->in.bpf_filter) {
         SCLogConfig("Using BPF '%s' on iface '%s'",
-                  aconf->bpf_filter, ntv->ifsrc->ifname);
+                  aconf->in.bpf_filter, ntv->ifsrc->ifname);
         if (pcap_compile_nopcap(default_packet_size,  /* snaplen_arg */
                     LINKTYPE_ETHERNET,    /* linktype_arg */
                     &ntv->bpf_prog,       /* program */
-                    aconf->bpf_filter,    /* const char *buf */
+                    aconf->in.bpf_filter, /* const char *buf */
                     1,                    /* optimize */
                     PCAP_NETMASK_UNKNOWN  /* mask */
-                    ) == -1) {
+                    ) == -1)
+        {
             SCLogError(SC_ERR_NETMAP_CREATE, "Filter compilation failed.");
             goto error_dst;
         }
@@ -758,7 +759,7 @@ static TmEcode ReceiveNetmapThreadInit(ThreadVars *tv, void *initdata, void **da
     SCReturnInt(TM_ECODE_OK);
 
 error_dst:
-    if (aconf->copy_mode != NETMAP_COPY_MODE_NONE) {
+    if (aconf->in.copy_mode != NETMAP_COPY_MODE_NONE) {
         NetmapClose(ntv->ifdst);
     }
 error_src:
index c6f7b6c23ff6b55a74aecceba8eeff7f9e38ecab..00b0b442743bbb77c32c74a8db35f5632f95a3b1 100644 (file)
@@ -35,25 +35,34 @@ enum {
 
 #define NETMAP_IFACE_NAME_LENGTH    48
 
-typedef struct NetmapIfaceConfig_
+typedef struct NetmapIfaceSettings_
 {
-    /* semantic interface name */
-    char iface_name[NETMAP_IFACE_NAME_LENGTH];
     /* real inner interface name */
     char iface[NETMAP_IFACE_NAME_LENGTH];
-    /* sw ring flag for iface */
-    int iface_sw;
+
     int threads;
+    /* sw ring flag for out_iface */
+    int sw_ring;
     int promisc;
     int copy_mode;
     ChecksumValidationMode checksum_mode;
     char *bpf_filter;
+} NetmapIfaceSettings;
+
+typedef struct NetmapIfaceConfig_
+{
+    /* semantic interface name */
+    char iface_name[NETMAP_IFACE_NAME_LENGTH];
+
+    /* settings for out capture device*/
+    NetmapIfaceSettings in;
+
     /* semantic interface name */
     char *out_iface_name;
-    /* real inner interface name */
-    char out_iface[NETMAP_IFACE_NAME_LENGTH];
-    /* sw ring flag for out_iface */
-    int out_iface_sw;
+
+    /* settings for outgoing iface for IPS/TAP */
+    NetmapIfaceSettings out;
+
     SC_ATOMIC_DECLARE(unsigned int, ref);
     void (*DerefFunc)(void *);
 } NetmapIfaceConfig;