]> git.ipfire.org Git - people/ms/suricata.git/commitdiff
ebpf: fix percpu hash handling
authorEric Leblond <eric@regit.org>
Sat, 9 Mar 2019 14:13:26 +0000 (15:13 +0100)
committerVictor Julien <victor@inliniac.net>
Tue, 18 Jun 2019 05:07:02 +0000 (07:07 +0200)
An alignement issue was preventing the code to work properly.
We introduce macros taken from Linux source code sample to get
something that should work on the long term.

src/source-af-packet.c
src/util-ebpf.c
src/util-ebpf.h

index d770050c00fbe3f71b05fa05213dc1c4716cdec0..d87776f56c7ed2e8cbbea594cebc0d8be08aebfe 100644 (file)
@@ -2299,7 +2299,7 @@ static int AFPInsertHalfFlow(int mapd, void *key, uint32_t hash,
                              uint64_t pkts_cnt, uint64_t bytes_cnt,
                              unsigned int nr_cpus)
 {
-    struct pair value[nr_cpus];
+    BPF_DECLARE_PERCPU(struct pair, value, nr_cpus);
     unsigned int i;
 
     if (mapd == -1) {
@@ -2310,12 +2310,13 @@ static int AFPInsertHalfFlow(int mapd, void *key, uint32_t hash,
      * is not duplicating the data on each CPU by itself. We set the first entry to
      * the actual flow pkts and bytes count as we need to continue from actual point
      * to detect an absence of packets in the future. */
-    value[0].packets = pkts_cnt;
-    value[0].bytes = bytes_cnt;
-    value[0].hash = hash;
+    BPF_PERCPU(value,0).packets = pkts_cnt;
+    BPF_PERCPU(value,0).bytes = bytes_cnt;
+    BPF_PERCPU(value,0).hash = hash;
     for (i = 1; i < nr_cpus; i++) {
-        value[i].packets = 0;
-        value[i].bytes = 0;
+        BPF_PERCPU(value, i).packets = 0;
+        BPF_PERCPU(value, i).bytes = 0;
+        BPF_PERCPU(value, i).hash = hash;
     }
     if (bpf_map_update_elem(mapd, key, value, BPF_NOEXIST) != 0) {
         switch (errno) {
index 7774b25163a439df1a64854303032651704024fa..4a5f25bd0a61f78e8836dc87818241b2f3b92ef0 100644 (file)
@@ -560,7 +560,7 @@ static int EBPFForEachFlowV4Table(LiveDevice *dev, const char *name,
         pkts_cnt = 0;
         /* We use a per CPU structure so we will get a array of values. But if nr_cpus
          * is 1 then we have a global hash. */
-        struct pair values_array[tcfg->cpus_count];
+        BPF_DECLARE_PERCPU(struct pair, values_array, tcfg->cpus_count);
         memset(values_array, 0, sizeof(values_array));
         int res = bpf_map_lookup_elem(mapfd, &next_key, values_array);
         if (res < 0) {
@@ -572,9 +572,10 @@ static int EBPFForEachFlowV4Table(LiveDevice *dev, const char *name,
         for (i = 0; i < tcfg->cpus_count; i++) {
             /* let's start accumulating value so we can compute the counters */
             SCLogDebug("%d: Adding pkts %lu bytes %lu", i,
-                       values_array[i].packets, values_array[i].bytes);
-            pkts_cnt += values_array[i].packets;
-            bytes_cnt += values_array[i].bytes;
+                       BPF_PERCPU(values_array, i).packets,
+                       BPF_PERCPU(values_array, i).bytes);
+            pkts_cnt += BPF_PERCPU(values_array, i).packets;
+            bytes_cnt += BPF_PERCPU(values_array, i).bytes;
         }
         /* Get the corresponding Flow in the Flow table to compare and update
          * its counters and lastseen if needed */
@@ -600,7 +601,8 @@ static int EBPFForEachFlowV4Table(LiveDevice *dev, const char *name,
         flow_key.vlan_id[1] = next_key.vlan_id[1];
         flow_key.proto = next_key.ip_proto;
         flow_key.recursion_level = 0;
-        pkts_cnt = EBPFOpFlowForKey(flowstats, &flow_key, values_array[0].hash,
+        pkts_cnt = EBPFOpFlowForKey(flowstats, &flow_key,
+                                    BPF_PERCPU(values_array, 0).hash,
                                     ctime, pkts_cnt, bytes_cnt);
         if (pkts_cnt > 0) {
             found = 1;
@@ -656,7 +658,7 @@ static int EBPFForEachFlowV6Table(LiveDevice *dev, const char *name,
         pkts_cnt = 0;
         /* We use a per CPU structure so we will get a array of values. But if nr_cpus
          * is 1 then we have a global hash. */
-        struct pair values_array[tcfg->cpus_count];
+        BPF_DECLARE_PERCPU(struct pair, values_array, tcfg->cpus_count);
         memset(values_array, 0, sizeof(values_array));
         int res = bpf_map_lookup_elem(mapfd, &next_key, values_array);
         if (res < 0) {
@@ -667,9 +669,10 @@ static int EBPFForEachFlowV6Table(LiveDevice *dev, const char *name,
         for (i = 0; i < tcfg->cpus_count; i++) {
             /* let's start accumulating value so we can compute the counters */
             SCLogDebug("%d: Adding pkts %lu bytes %lu", i,
-                       values_array[i].packets, values_array[i].bytes);
-            pkts_cnt += values_array[i].packets;
-            bytes_cnt += values_array[i].bytes;
+                       BPF_PERCPU(values_array, i).packets,
+                       BPF_PERCPU(values_array, i).bytes);
+            pkts_cnt += BPF_PERCPU(values_array, i).packets;
+            bytes_cnt += BPF_PERCPU(values_array, i).bytes;
         }
         /* Get the corresponding Flow in the Flow table to compare and update
          * its counters  and lastseen if needed */
@@ -695,7 +698,7 @@ static int EBPFForEachFlowV6Table(LiveDevice *dev, const char *name,
         flow_key.vlan_id[1] = next_key.vlan_id[1];
         flow_key.proto = next_key.ip_proto;
         flow_key.recursion_level = 0;
-        pkts_cnt = EBPFOpFlowForKey(flowstats, &flow_key, values_array[0].hash,
+        pkts_cnt = EBPFOpFlowForKey(flowstats, &flow_key, BPF_PERCPU(values_array, 0).hash,
                                     ctime, pkts_cnt, bytes_cnt);
         if (pkts_cnt > 0) {
             found = 1;
index c66c1d9e2e2df2bd9aada7285d832e9f2522c224..078870aa4b4126c01d851aa9cf3eb73412f3a892 100644 (file)
@@ -88,6 +88,14 @@ int EBPFUpdateFlow(Flow *f, Packet *p, void *data);
 TmEcode EBPFGetBypassedStats(json_t *cmd, json_t *answer, void *data);
 #endif
 
+#define __bpf_percpu_val_align  __attribute__((__aligned__(8)))
+
+#define BPF_DECLARE_PERCPU(type, name, nr_cpus)                          \
+        struct { type v; /* padding */ } __bpf_percpu_val_align \
+                name[nr_cpus]
+#define BPF_PERCPU(name, cpu) name[(cpu)].v
+
+
 #endif
 
 #endif