From: Max Fillinger Date: Fri, 5 Jul 2019 14:59:36 +0000 (+0200) Subject: flow hash: Make CMP_FLOW macro an inline function X-Git-Tag: suricata-5.0.0-rc1~209 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=38731d30da10284c7790f1965ced8e2f7f1da5da;p=thirdparty%2Fsuricata.git flow hash: Make CMP_FLOW macro an inline function --- diff --git a/src/flow-hash.c b/src/flow-hash.c index ee644cd224..5afa154304 100644 --- a/src/flow-hash.c +++ b/src/flow-hash.c @@ -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