]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
util-ebpf: implement pinned maps loading
authorEric Leblond <eric@regit.org>
Sun, 9 Dec 2018 22:22:08 +0000 (23:22 +0100)
committerVictor Julien <victor@inliniac.net>
Tue, 18 Jun 2019 05:07:02 +0000 (07:07 +0200)
Load flow tables at start if asked to.

doc/userguide/capture-hardware/ebpf-xdp.rst
src/runmode-af-packet.c
src/util-ebpf.c

index bab638929b7cca586f3ac7e5c60a43d8be7e39fe..92fdb7e9c19eed37008c9712012b0ef360173b58 100644 (file)
@@ -359,7 +359,7 @@ Confirm you have the XDP filter engaged in the output (example)::
 Pinned maps usage
 -----------------
 
-Pnned maps stay attached to the system if the creating process disappear and
+Pinned maps stay attached to the system if the creating process disappear and
 they can also be accessed by external tools. In Suricata bypass case, this can be
 used to keep active bypassed flow tables so Suricata is not hit by previsouly bypassed flows when
 restarting. In the socket filter case, this can be used to maintain a map from tools outside
index 64ac73b95677856526f404cdeba31560a05981b1..920fac8a3309dcf5db47ccc6b5ab0fecebafb6fd 100644 (file)
@@ -457,6 +457,7 @@ static void *ParseAFPConfig(const char *iface)
         aconf->ebpf_t_config.mode = AFP_MODE_XDP_BYPASS;
         aconf->ebpf_t_config.flags |= EBPF_XDP_CODE;
         aconf->xdp_filter_file = ebpf_file;
+        /* TODO FIXME Do we really have a usage of setting XDP and not bypassing ? */
         ConfGetChildValueBoolWithDefault(if_root, if_default, "bypass", &conf_val);
         if (conf_val) {
 #ifdef HAVE_PACKET_XDP
index 2b8def0da56466241543c148fa98be61657b4743..0bb1b4ffac87cc7f49331fb88406644a6353ff46 100644 (file)
@@ -153,9 +153,57 @@ int EBPFGetMapFDByName(const char *iface, const char *name)
             return bpf_maps->array[i].fd;
         }
     }
+
+    /* Fallback by getting pinned maps ? */
+
     return -1;
 }
 
+static int EBPFLoadPinnedMapsFile(LiveDevice *livedev, const char *file)
+{
+    char pinnedpath[1024];
+    snprintf(pinnedpath, sizeof(pinnedpath),
+            "/sys/fs/bpf/suricata-%s-%s",
+            livedev->dev,
+            file);
+
+    return bpf_obj_get(pinnedpath);
+}
+
+static int EBPFLoadPinnedMaps(LiveDevice *livedev, uint8_t flags)
+{
+    int fd_v4 = -1, fd_v6 = -1;
+
+    /* Get flow v4 table */
+    fd_v4 = EBPFLoadPinnedMapsFile(livedev, "flow_table_v4");
+    if (fd_v4 < 0) {
+        return fd_v4;
+    }
+
+    /* Get flow v6 table */
+    fd_v6 = EBPFLoadPinnedMapsFile(livedev, "flow_table_v6");
+    if (fd_v6 < 0) {
+        SCLogWarning(SC_ERR_INVALID_ARGUMENT,
+                     "Found a flow_table_v4 map but no flow_table_v6 map");
+        return fd_v6;
+    }
+
+    struct bpf_maps_info *bpf_map_data = SCCalloc(1, sizeof(*bpf_map_data));
+    if (bpf_map_data == NULL) {
+        SCLogError(SC_ERR_MEM_ALLOC, "Can't allocate bpf map array");
+        return -1;
+    }
+    SC_ATOMIC_INIT(bpf_map_data->ipv4_hash_count);
+    SC_ATOMIC_INIT(bpf_map_data->ipv6_hash_count);
+    bpf_map_data->array[0].fd = fd_v4;
+    bpf_map_data->array[0].name = SCStrdup("flow_table_v4");
+    bpf_map_data->array[1].fd = fd_v6;
+    bpf_map_data->array[1].name = SCStrdup("flow_table_v6");
+    bpf_map_data->last = 2;
+
+    return 0;
+}
+
 /**
  * Load a section of an eBPF file
  *
@@ -183,6 +231,13 @@ int EBPFLoadFile(const char *iface, const char *path, const char * section,
     if (livedev == NULL)
         return -1;
 
+    if (flags & EBPF_XDP_CODE) {
+        /* We try to get our flow table maps and if we have them we can simply return */
+        if (EBPFLoadPinnedMaps(livedev, flags) == 0) {
+            return 0;
+        }
+    }
+
     if (! path) {
         SCLogError(SC_ERR_INVALID_VALUE, "No file defined to load eBPF from");
         return -1;