]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
ebpf: get rid of hash in map value
authorEric Leblond <eric@regit.org>
Sun, 9 Jun 2019 20:09:42 +0000 (22:09 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 18 Jun 2019 05:07:02 +0000 (07:07 +0200)
ebpf/xdp_filter.c
src/flow-hash.c
src/flow-hash.h
src/source-af-packet.c
src/util-ebpf.c
src/util-ebpf.h

index 229a912e6b5cc8d1e54175626dc4e5c499a6e411..ff00cef3f2484426d756e8e044968688ca3ffea1 100644 (file)
@@ -90,7 +90,6 @@ struct flowv6_keys {
 struct pair {
     __u32 packets;
     __u32 bytes;
-    __u32 hash;
 };
 
 struct bpf_map_def SEC("maps") flow_table_v4 = {
index 1c795a51a51bb3b6b789cdeee4e537b1820e5675..4c4b6ae22267e6f3b953126027ae5e76e4aefc41 100644 (file)
@@ -210,6 +210,19 @@ static inline uint32_t FlowGetHash(const Packet *p)
     return hash;
 }
 
+/**
+ * Basic hashing function for FlowKey
+ *
+ * \note Function only used for bypass
+ *
+ * \note this is only used at start to create Flow from pinned maps
+ * so fairness is not an issue
+ */
+uint32_t FlowKeyGetHash(FlowKey *fk)
+{
+    return hashword((uint32_t *)fk, sizeof(*fk)/4, flow_config.hash_rand);
+}
+
 /* Since two or more flows can have the same hash key, we need to compare
  * the flow with the current flow key. */
 #define CMP_FLOW(f1,f2) \
index d70c4d377a615f2410b6382c88950513a804eb4a..b5853b7d5195cf661c36b1db1f43f4f9b1b141a9 100644 (file)
@@ -78,6 +78,7 @@ Flow *FlowGetFlowFromHash(ThreadVars *tv, DecodeThreadVars *dtv, const Packet *,
 
 Flow *FlowGetFromFlowKey(FlowKey *key, struct timespec *ttime, const uint32_t hash);
 Flow *FlowGetExistingFlowFromHash(FlowKey * key, uint32_t hash);
+uint32_t FlowKeyGetHash(FlowKey *flow_key);
 
 void FlowDisableTcpReuseHandling(void);
 
index 9645b781a60e6b4a4cdc065cfb3a7a874ba0b167..52676838d29ece778709dc3ff3240efa8bfa4395 100644 (file)
@@ -2294,8 +2294,7 @@ TmEcode AFPSetBPFFilter(AFPThreadVars *ptv)
  * \param key data to use as key in the table
  * \return 0 in case of error, 1 if success
  */
-static int AFPInsertHalfFlow(int mapd, void *key, uint32_t hash,
-                             unsigned int nr_cpus)
+static int AFPInsertHalfFlow(int mapd, void *key, unsigned int nr_cpus)
 {
     BPF_DECLARE_PERCPU(struct pair, value, nr_cpus);
     unsigned int i;
@@ -2309,7 +2308,6 @@ static int AFPInsertHalfFlow(int mapd, void *key, uint32_t hash,
     for (i = 0; i < nr_cpus; i++) {
         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) {
@@ -2409,7 +2407,7 @@ static int AFPBypassCallback(Packet *p)
         keys[0]->vlan_id[1] = p->vlan_id[1];
 
         keys[0]->ip_proto = IPV4_GET_IPPROTO(p);
-        if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[0], p->flow_hash,
+        if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[0],
                               p->afp_v.nr_cpus) == 0) {
             SCFree(keys[0]);
             return 0;
@@ -2427,7 +2425,7 @@ static int AFPBypassCallback(Packet *p)
         keys[1]->vlan_id[1] = p->vlan_id[1];
 
         keys[1]->ip_proto = IPV4_GET_IPPROTO(p);
-        if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[1], p->flow_hash,
+        if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[1],
                               p->afp_v.nr_cpus) == 0) {
             SCFree(keys[0]);
             SCFree(keys[1]);
@@ -2458,7 +2456,7 @@ static int AFPBypassCallback(Packet *p)
         keys[0]->vlan_id[0] = p->vlan_id[0];
         keys[0]->vlan_id[1] = p->vlan_id[1];
         keys[0]->ip_proto = IPV6_GET_NH(p);
-        if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[0], p->flow_hash,
+        if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[0],
                               p->afp_v.nr_cpus) == 0) {
             SCFree(keys[0]);
             return 0;
@@ -2477,7 +2475,7 @@ static int AFPBypassCallback(Packet *p)
         keys[1]->vlan_id[0] = p->vlan_id[0];
         keys[1]->vlan_id[1] = p->vlan_id[1];
         keys[1]->ip_proto = IPV6_GET_NH(p);
-        if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[1], p->flow_hash,
+        if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[1],
                               p->afp_v.nr_cpus) == 0) {
             SCFree(keys[0]);
             SCFree(keys[1]);
@@ -2542,7 +2540,7 @@ static int AFPXDPBypassCallback(Packet *p)
         keys[0]->vlan_id[0] = p->vlan_id[0];
         keys[0]->vlan_id[1] = p->vlan_id[1];
         keys[0]->ip_proto = IPV4_GET_IPPROTO(p);
-        if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[0], p->flow_hash,
+        if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[0],
                               p->afp_v.nr_cpus) == 0) {
             SCFree(keys[0]);
             return 0;
@@ -2559,7 +2557,7 @@ static int AFPXDPBypassCallback(Packet *p)
         keys[1]->vlan_id[0] = p->vlan_id[0];
         keys[1]->vlan_id[1] = p->vlan_id[1];
         keys[1]->ip_proto = IPV4_GET_IPPROTO(p);
-        if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[1], p->flow_hash,
+        if (AFPInsertHalfFlow(p->afp_v.v4_map_fd, keys[1],
                               p->afp_v.nr_cpus) == 0) {
             SCFree(keys[0]);
             SCFree(keys[1]);
@@ -2590,7 +2588,7 @@ static int AFPXDPBypassCallback(Packet *p)
         keys[0]->vlan_id[0] = p->vlan_id[0];
         keys[0]->vlan_id[1] = p->vlan_id[1];
         keys[0]->ip_proto = IPV6_GET_NH(p);
-        if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[0], p->flow_hash,
+        if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[0],
                               p->afp_v.nr_cpus) == 0) {
             SCFree(keys[0]);
             return 0;
@@ -2609,7 +2607,7 @@ static int AFPXDPBypassCallback(Packet *p)
         keys[1]->vlan_id[0] = p->vlan_id[0];
         keys[1]->vlan_id[1] = p->vlan_id[1];
         keys[1]->ip_proto = IPV6_GET_NH(p);
-        if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[1], p->flow_hash,
+        if (AFPInsertHalfFlow(p->afp_v.v6_map_fd, keys[1],
                               p->afp_v.nr_cpus) == 0) {
             SCFree(keys[0]);
             SCFree(keys[1]);
index bc3e1e9cbc0b8d6af7307c3d36c4728952fa54a3..c507494f516298dc8034ca7d9684f359d960079f 100644 (file)
@@ -501,11 +501,15 @@ int EBPFSetupXDP(const char *iface, int fd, uint8_t flags)
  *
  * \return false (this create function never returns true)
  */
-static bool EBPFCreateFlowForKey(struct flows_stats *flowstats, FlowKey *flow_key,
-                                uint32_t hash, struct timespec *ctime,
-                                uint64_t pkts_cnt, uint64_t bytes_cnt)
+static bool EBPFCreateFlowForKey(struct flows_stats *flowstats, void *key,
+                                 FlowKey *flow_key, struct timespec *ctime,
+                                 uint64_t pkts_cnt, uint64_t bytes_cnt,
+                                 int mapfd, int cpus_count)
 {
-    Flow *f = FlowGetFromFlowKey(flow_key, ctime, hash);
+    Flow *f = NULL;
+    uint32_t hash = FlowKeyGetHash(flow_key);
+
+    f = FlowGetFromFlowKey(flow_key, ctime, hash);
     if (f == NULL)
         return false;
 
@@ -523,6 +527,16 @@ static bool EBPFCreateFlowForKey(struct flows_stats *flowstats, FlowKey *flow_ke
             fc->BypassFree = EBPFBypassFree;
             fc->todstpktcnt = pkts_cnt;
             fc->todstbytecnt = bytes_cnt;
+            EBPFBypassData *eb = SCCalloc(1, sizeof(EBPFBypassData));
+            if (eb == NULL) {
+                SCFree(fc);
+                FLOWLOCK_UNLOCK(f);
+                return false;
+            }
+            eb->key[0] = key;
+            eb->mapfd = mapfd;
+            eb->cpus_count = cpus_count;
+            fc->bypass_data = eb;
         } else {
             FLOWLOCK_UNLOCK(f);
             return false;
@@ -530,6 +544,10 @@ static bool EBPFCreateFlowForKey(struct flows_stats *flowstats, FlowKey *flow_ke
     } else {
         fc->tosrcpktcnt = pkts_cnt;
         fc->tosrcbytecnt = bytes_cnt;
+        EBPFBypassData *eb = (EBPFBypassData *) fc->bypass_data;
+        if (eb) {
+            eb->key[1] = key;
+        }
     }
     FLOWLOCK_UNLOCK(f);
     return false;
@@ -627,9 +645,10 @@ bool EBPFBypassUpdate(Flow *f, void *data, time_t tsec)
     return false;
 }
 
-typedef bool (*OpFlowForKey)(struct flows_stats *flowstats, FlowKey *flow_key,
-                            uint32_t hash, struct timespec *ctime,
-                            uint64_t pkts_cnt, uint64_t bytes_cnt);
+typedef bool (*OpFlowForKey)(struct flows_stats *flowstats, void *key,
+                            FlowKey *flow_key, struct timespec *ctime,
+                            uint64_t pkts_cnt, uint64_t bytes_cnt,
+                            int mapfd, int cpus_count);
 
 /**
  * Bypassed flows cleaning for IPv4
@@ -709,9 +728,9 @@ static int EBPFForEachFlowV4Table(ThreadVars *th_v, LiveDevice *dev, const char
         flow_key.vlan_id[1] = next_key.vlan_id[1];
         flow_key.proto = next_key.ip_proto;
         flow_key.recursion_level = 0;
-        dead_flow = EBPFOpFlowForKey(flowstats, &flow_key,
-                                    BPF_PERCPU(values_array, 0).hash,
-                                    ctime, pkts_cnt, bytes_cnt);
+        dead_flow = EBPFOpFlowForKey(flowstats, &next_key, &flow_key,
+                                     ctime, pkts_cnt, bytes_cnt,
+                                     mapfd, tcfg->cpus_count);
         if (dead_flow) {
             found = 1;
         }
@@ -818,8 +837,9 @@ static int EBPFForEachFlowV6Table(ThreadVars *th_v,
         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, BPF_PERCPU(values_array, 0).hash,
-                                    ctime, pkts_cnt, bytes_cnt);
+        pkts_cnt = EBPFOpFlowForKey(flowstats, &next_key, &flow_key,
+                                    ctime, pkts_cnt, bytes_cnt,
+                                    mapfd, tcfg->cpus_count);
         if (pkts_cnt > 0) {
             found = 1;
         }
index 043f137e8c517b002295372828ca5ce6e1d1bd14..818283d7af25597e1a6face4edc274bcb34c2d22 100644 (file)
@@ -58,7 +58,6 @@ struct flowv6_keys {
 struct pair {
     uint32_t packets;
     uint32_t bytes;
-    uint32_t hash;
 };
 
 typedef struct EBPFBypassData_ {