|
|
|
|
@ -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
|
|
|
|
|
|