/*************************************************************************
* (C) 2022 CloudSigma AG - Sofia/Bulgaria
* by Michael Pounov <misho@elwix.org>
**************************************************************************/
#include "fwsync.h"
#ifndef IPFIREWALL_JENKINSHASH
__inline uint32_t
fwsync_hash_packet(const struct ipfw_flow_id *id)
{
uint32_t i;
#ifdef INET6
if (IS_IP6_FLOW_ID(id))
i = ntohl((id->dst_ip6.__u6_addr.__u6_addr32[2]) ^
(id->dst_ip6.__u6_addr.__u6_addr32[3]) ^
(id->src_ip6.__u6_addr.__u6_addr32[2]) ^
(id->src_ip6.__u6_addr.__u6_addr32[3]));
else
#endif /* INET6 */
i = (id->dst_ip) ^ (id->src_ip);
i ^= (id->dst_port) ^ (id->src_port);
return (i);
}
__inline uint32_t
fwsync_hash_parent(const struct ipfw_flow_id *id, const void *rule)
{
return (fwsync_hash_packet(id) ^ ((uintptr_t)rule));
}
#else /* IPFIREWALL_JENKINSHASH */
VNET_DEFINE_STATIC(uint32_t, dyn_hashseed);
#define V_dyn_hashseed VNET(dyn_hashseed)
static __inline int
addrcmp4(const struct ipfw_flow_id *id)
{
if (id->src_ip < id->dst_ip)
return (0);
if (id->src_ip > id->dst_ip)
return (1);
if (id->src_port <= id->dst_port)
return (0);
return (1);
}
#ifdef INET6
static __inline int
addrcmp6(const struct ipfw_flow_id *id)
{
int ret;
ret = memcmp(&id->src_ip6, &id->dst_ip6, sizeof(struct in6_addr));
if (ret < 0)
return (0);
if (ret > 0)
return (1);
if (id->src_port <= id->dst_port)
return (0);
return (1);
}
__inline uint32_t
fwsync_hash_packet6(const struct ipfw_flow_id *id)
{
struct tuple6 {
struct in6_addr addr[2];
uint16_t port[2];
} t6;
if (addrcmp6(id) == 0) {
t6.addr[0] = id->src_ip6;
t6.addr[1] = id->dst_ip6;
t6.port[0] = id->src_port;
t6.port[1] = id->dst_port;
} else {
t6.addr[0] = id->dst_ip6;
t6.addr[1] = id->src_ip6;
t6.port[0] = id->dst_port;
t6.port[1] = id->src_port;
}
return (jenkins_hash32((const uint32_t *)&t6,
sizeof(t6) / sizeof(uint32_t), V_dyn_hashseed));
}
#endif
__inline uint32_t
fwsync_hash_packet(const struct ipfw_flow_id *id)
{
struct tuple4 {
in_addr_t addr[2];
uint16_t port[2];
} t4;
if (IS_IP4_FLOW_ID(id)) {
/* All fields are in host byte order */
if (addrcmp4(id) == 0) {
t4.addr[0] = id->src_ip;
t4.addr[1] = id->dst_ip;
t4.port[0] = id->src_port;
t4.port[1] = id->dst_port;
} else {
t4.addr[0] = id->dst_ip;
t4.addr[1] = id->src_ip;
t4.port[0] = id->dst_port;
t4.port[1] = id->src_port;
}
return (jenkins_hash32((const uint32_t *)&t4,
sizeof(t4) / sizeof(uint32_t), V_dyn_hashseed));
} else
#ifdef INET6
if (IS_IP6_FLOW_ID(id))
return (fwsync_hash_packet6(id));
#endif
return (0);
}
__inline uint32_t
fwsync_hash_parent(const struct ipfw_flow_id *id, const void *rule)
{
return (jenkins_hash32((const uint32_t *)&rule,
sizeof(rule) / sizeof(uint32_t), fwsync_hash_packet(id)));
}
#endif /* IPFIREWALL_JENKINSHASH */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>