]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
flow hash: Make CMP_FLOW macro an inline function
authorMax Fillinger <maximilian.fillinger@fox-it.com>
Fri, 5 Jul 2019 14:59:36 +0000 (16:59 +0200)
committerMax Fillinger <maximilian.fillinger@fox-it.com>
Wed, 10 Jul 2019 10:10:22 +0000 (12:10 +0200)
src/flow-hash.c

index ee644cd224dc20254bcf92805090781a72475ead..5afa154304e4455e5824a193c16f55082a52d182 100644 (file)
@@ -274,30 +274,82 @@ uint32_t FlowKeyGetHash(FlowKey *fk)
 return hash;
 }
 
+static inline bool CmpAddrs(const uint32_t addr1[4], const uint32_t addr2[4])
+{
+    return addr1[0] == addr2[0] && addr1[1] == addr2[1] &&
+        addr1[2] == addr2[2] && addr1[3] == addr2[3];
+}
+
+static inline bool CmpAddrsAndPorts(const uint32_t src1[4],
+    const uint32_t dst1[4], Port src_port1, Port dst_port1,
+    const uint32_t src2[4], const uint32_t dst2[4], Port src_port2,
+    Port dst_port2)
+{
+    /* Compare the source and destination addresses. If they are not equal,
+     * compare the first source address with the second destination address,
+     * and vice versa. Likewise for ports. */
+    return (CmpAddrs(src1, src2) && CmpAddrs(dst1, dst2) &&
+        src_port1 == src_port2 && dst_port1 == dst_port2) ||
+        (CmpAddrs(src1, dst2) && CmpAddrs(dst1, src2) &&
+        src_port1 == dst_port2 && dst_port1 == src_port2);
+}
+
+static inline bool CmpVlanIds(const uint16_t vlan_id1[2], const uint16_t vlan_id2[2])
+{
+    return vlan_id1[0] == vlan_id2[0] && vlan_id1[1] == vlan_id2[1];
+}
+
 /* 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) \
-    (((CMP_ADDR(&(f1)->src, &(f2)->src) && \
-       CMP_ADDR(&(f1)->dst, &(f2)->dst) && \
-       CMP_PORT((f1)->sp, (f2)->sp) && CMP_PORT((f1)->dp, (f2)->dp)) || \
-      (CMP_ADDR(&(f1)->src, &(f2)->dst) && \
-       CMP_ADDR(&(f1)->dst, &(f2)->src) && \
-       CMP_PORT((f1)->sp, (f2)->dp) && CMP_PORT((f1)->dp, (f2)->sp))) && \
-     (f1)->proto == (f2)->proto && \
-     (f1)->recursion_level == (f2)->recursion_level && \
-     (f1)->vlan_id[0] == (f2)->vlan_id[0] && \
-     (f1)->vlan_id[1] == (f2)->vlan_id[1])
-#define CMP_FLOW_ICMP(f1,f2) \
-    (((CMP_ADDR(&(f1)->src, &(f2)->src) && \
-       CMP_ADDR(&(f1)->dst, &(f2)->dst) && \
-       CMP_PORT((f1)->icmp_s.type, (f2)->icmp_s.type) && CMP_PORT((f1)->icmp_d.type, (f2)->icmp_d.type)) || \
-      (CMP_ADDR(&(f1)->src, &(f2)->dst) && \
-       CMP_ADDR(&(f1)->dst, &(f2)->src) && \
-       CMP_PORT((f1)->icmp_d.type, (f2)->icmp_s.type) && CMP_PORT((f1)->icmp_s.type, (f2)->icmp_d.type))) && \
-     (f1)->proto == (f2)->proto && \
-     (f1)->recursion_level == (f2)->recursion_level && \
-     (f1)->vlan_id[0] == (f2)->vlan_id[0] && \
-     (f1)->vlan_id[1] == (f2)->vlan_id[1])
+ * the flow with the current packet or flow key. */
+static inline bool CmpFlowPacket(const Flow *f, const Packet *p)
+{
+    const uint32_t *f_src = f->src.address.address_un_data32;
+    const uint32_t *f_dst = f->dst.address.address_un_data32;
+    const uint32_t *p_src = p->src.address.address_un_data32;
+    const uint32_t *p_dst = p->dst.address.address_un_data32;
+    return CmpAddrsAndPorts(f_src, f_dst, f->sp, f->dp, p_src, p_dst, p->sp,
+        p->dp) && f->proto == p->proto &&
+        f->recursion_level == p->recursion_level &&
+        CmpVlanIds(f->vlan_id, p->vlan_id);
+}
+
+static inline bool CmpFlowKey(const Flow *f, const FlowKey *k)
+{
+    const uint32_t *f_src = f->src.address.address_un_data32;
+    const uint32_t *f_dst = f->dst.address.address_un_data32;
+    const uint32_t *k_src = k->src.address.address_un_data32;
+    const uint32_t *k_dst = k->dst.address.address_un_data32;
+    return CmpAddrsAndPorts(f_src, f_dst, f->sp, f->dp, k_src, k_dst, k->sp,
+        k->dp) && f->proto == k->proto &&
+        f->recursion_level == k->recursion_level &&
+        CmpVlanIds(f->vlan_id, k->vlan_id);
+}
+
+static inline bool CmpAddrsAndICMPTypes(const uint32_t src1[4],
+    const uint32_t dst1[4], uint8_t icmp_s_type1, uint8_t icmp_d_type1,
+    const uint32_t src2[4], const uint32_t dst2[4], uint8_t icmp_s_type2,
+    uint8_t icmp_d_type2)
+{
+    /* Compare the source and destination addresses. If they are not equal,
+     * compare the first source address with the second destination address,
+     * and vice versa. Likewise for icmp types. */
+    return (CmpAddrs(src1, src2) && CmpAddrs(dst1, dst2) &&
+        icmp_s_type1 == icmp_s_type2 && icmp_d_type1 == icmp_d_type2) ||
+        (CmpAddrs(src1, dst2) && CmpAddrs(dst1, src2) &&
+        icmp_s_type1 == icmp_d_type2 && icmp_d_type1 == icmp_s_type2);
+}
+
+static inline bool CmpFlowICMPPacket(const Flow *f, const Packet *p)
+{
+    const uint32_t *f_src = f->src.address.address_un_data32;
+    const uint32_t *f_dst = f->dst.address.address_un_data32;
+    const uint32_t *p_src = p->src.address.address_un_data32;
+    const uint32_t *p_dst = p->dst.address.address_un_data32;
+    return CmpAddrsAndICMPTypes(f_src, f_dst, f->icmp_s.type,
+        f->icmp_d.type, p_src, p_dst, p->icmp_s.type, p->icmp_d.type) &&
+        f->proto == p->proto && f->recursion_level == p->recursion_level &&
+        CmpVlanIds(f->vlan_id, p->vlan_id);
+}
 
 /**
  *  \brief See if a ICMP packet belongs to a flow by comparing the embedded
@@ -343,7 +395,7 @@ static inline int FlowCompareICMPv4(Flow *f, const Packet *p)
         /* no match, fall through */
     } else {
         /* just treat ICMP as a normal proto for now */
-        return CMP_FLOW_ICMP(f, p);
+        return CmpFlowICMPPacket(f, p);
     }
 
     return 0;
@@ -362,7 +414,7 @@ static inline int FlowCompare(Flow *f, const Packet *p)
     if (p->proto == IPPROTO_ICMP) {
         return FlowCompareICMPv4(f, p);
     } else if (p->proto == IPPROTO_TCP) {
-        if (CMP_FLOW(f, p) == 0)
+        if (CmpFlowPacket(f, p) == 0)
             return 0;
 
         /* if this session is 'reused', we don't return it anymore,
@@ -372,7 +424,7 @@ static inline int FlowCompare(Flow *f, const Packet *p)
 
         return 1;
     } else {
-        return CMP_FLOW(f, p);
+        return CmpFlowPacket(f, p);
     }
 }
 
@@ -670,7 +722,7 @@ static inline int FlowCompareKey(Flow *f, FlowKey *key)
 {
     if ((f->proto != IPPROTO_TCP) && (f->proto != IPPROTO_UDP))
         return 0;
-    return CMP_FLOW(f, key);
+    return CmpFlowKey(f, key);
 }
 
 /** \brief Get or create a Flow using a FlowKey