linux内核netfilter连接跟踪的hash算法

转载 2007年10月14日 22:06:00
原贴:http://zhuaxia.com/item/73625059

linux内核netfilter连接跟踪的hash算法

 

linux内核中的netfilter是一款强大的基于状态的防火墙,具有连接跟踪(conntrack)的实现。conntracknetfilter的核心,许多增强的功能,例如,地址转换(NAT),基于内容的业务识别(l7 layer-7 module)都是基于连接跟踪。然而,netfilter的性能还有很多值得改进的地方。

netfilter的连接跟踪的hash算法是在Bob Jenkinslookup2.c基础上的改进实现,Bob Jenkins已经推出lookup3.c的实现,见地址:http://burtleburtle.net/bob/hash/http://burtleburtle.net/bob/c/lookup3.c

netfilter中的hash求值的代码如下:

 

static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple,

                              unsigned int size, unsigned int rnd)

{

       unsigned int a, b;

       a = jhash((void *)tuple->src.u3.all, sizeof(tuple->src.u3.all),

                ((tuple->src.l3num) << 16) | tuple->dst.protonum);

       b = jhash((void *)tuple->dst.u3.all, sizeof(tuple->dst.u3.all),

                     (tuple->src.u.all << 16) | tuple->dst.u.all);

 

       return jhash_2words(a, b, rnd) % size;

}

 

static inline u_int32_t hash_conntrack(const struct nf_conntrack_tuple *tuple)

{

       return __hash_conntrack(tuple, nf_conntrack_htable_size,

                            nf_conntrack_hash_rnd);

}

 

这是一个对于ipv6ipv4hash求值的通用实现。struct nf_conntrack_tuple是一个通用的连接的四元组,同时用于ipv4ipv6tcpudpsctpicmp协议,所以,其定义比较复杂。可以把它理解为源地址,源端口,目的地址,目的端口。

#define NF_CT_TUPLE_L3SIZE  4

union nf_conntrack_man_l3proto {

       u_int32_t all[NF_CT_TUPLE_L3SIZE];

       u_int32_t ip;

       u_int32_t ip6[4];

};

其实这就是ip地址。

union nf_conntrack_man_proto

{

       /* Add other protocols here. */

       u_int16_t all;

 

       struct {

              u_int16_t port;

       } tcp;

       struct {

              u_int16_t port;

       } udp;

       struct {

              u_int16_t id;

       } icmp;

       struct {

              u_int16_t port;

       } sctp;

};

这就是端口。

struct nf_conntrack_man

{

       union nf_conntrack_man_l3proto u3;

       union nf_conntrack_man_proto u;

       /* Layer 3 protocol */

       u_int16_t l3num;

};

目的地址和端口,l3num不知道是什么东西?

struct nf_conntrack_tuple

{

       struct nf_conntrack_man src;

 

       /* These are the parts of the tuple which are fixed. */

       struct {

              union {

                     u_int32_t all[NF_CT_TUPLE_L3SIZE];

                     u_int32_t ip;

                     u_int32_t ip6[4];

              } u3;

              union {

                     /* Add other protocols here. */

                     u_int16_t all;

 

                     struct {

                            u_int16_t port;

                     } tcp;

                     struct {

                            u_int16_t port;

                     } udp;

                     struct {

                            u_int8_t type, code;

                     } icmp;

                     struct {

                            u_int16_t port;

                     } sctp;

              } u;

 

              /* The protocol. */

              u_int8_t protonum;

 

              /* The direction (for tuplehash) */

              u_int8_t dir;

       } dst;

};

有些混乱,就是源地址和目的地址,protonumdir不知道为什么这么定义?

 

 

上面的hash算法在仅用于ipv4时,可以进行优化。jhash函数是通用的hash函数,上面的目的是把ipv6的长串字符hash为一个32位整数,而ipv4的情况下,可以不用。

 

最后,使用%运算,这是非常低效的,Bob Jenkins专门指出了这一点。由于table的大小都为2的次方,所以,可以使用&的算法。

 

另外,我认为Bob Jenkins的算法是对于通用的数字的hash算法,对于tcp连接这样比较特殊的数字的hash,使用这么复杂的算法,是否有意义?简单的加法运算是否更有效率?

 

lookup3.clookup2.c有很大的不同。lookup3.c中,使用了final宏,和mix宏分开。而lookup2.c中没有使用final宏。

 

linux下的修改过的hash函数:

static inline u32 jhash(const void *key, u32 length, u32 initval)

通用的hash函数,对任意长度的key字符串进行hash运算,得到一个32位数字。

 

static inline u32 jhash2(u32 *k, u32 length, u32 initval)

优化的版本,对任意长度的32位整数进行hash运算,得到一个32位数字。

static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)

{

       a += JHASH_GOLDEN_RATIO;

       b += JHASH_GOLDEN_RATIO;

       c += initval;

 

       __jhash_mix(a, b, c);

 

       return c;

}

优化的版本,对332位整数进行hash运算,得到一个32位数字。

static inline u32 jhash_2words(u32 a, u32 b, u32 initval)

{

       return jhash_3words(a, b, 0, initval);

}

232位整数进行hash运算,得到一个32位数字。

 

static inline u32 jhash_1word(u32 a, u32 initval)

{

       return jhash_3words(a, 0, 0, initval);

}

132位整数进行hash运算,得到一个32位数字。

 

 

 

 

上面的两个宏这是lookup3.c的核心hash算法,hash的基础。

 

 

 

 

 

hashword是通用的hash算法,用于计算任意cpu架构,任意长度的字符串的hash值。

 

不断的把输入的串k,每隔3位进行mix,直到完毕。返回final

 

对于ipv4的话,可以直接把源地址,目的地址,(源端口<< 16)|目的端口,这三个整数进行final,得到hash值。

 

对于ip地址和端口号的特点,这种复杂的算法是否真的有更好的hash效果,我持怀疑态度。

 

使用Jhash替换传统hash有效降低hash冲突提供查找效率

“`includeincludeinclude”jhash.h”//常规算法的黄金分隔define VOICE_HASH_GOLDEN_INTERER 0x9e370001//hash桶的大小为2...
  • qiujiahao123
  • qiujiahao123
  • 2017-03-22 21:20:16
  • 906

Linux之Makefile(words)

$(words TEXT)  函数名称:统计单词数目函数—words。  函数功能:字算字串“TEXT”中单词的数目。  返回值:“TEXT”字串中的单词数。  示例:  $(words, ...
  • zhoudengqing
  • zhoudengqing
  • 2014-12-06 19:54:07
  • 1120

Linux内核Jhash

static uint32_t jhash(const void *key, unsigned int length, unsigned int initval); static int32_t m...
  • qisefengzheng
  • qisefengzheng
  • 2016-04-01 09:30:49
  • 1879

Linux内核中TCP的连接跟踪(2)

TCP filter的原理: 当filter收到某个连接的第一个报文时,会为该连接在全局连接表中创建一个表项,并用报文中携带的源、目的IP和端口这个四元组创建original tuple和rep...
  • jianchaolv
  • jianchaolv
  • 2012-09-11 11:45:47
  • 1879

IPv6详解:SHA1算法实现及详解

安全哈希算法(Secure Hash Algorithm) SHA1是一种数据加密的算法,其思想就是将一段明文加密成一个不可逆的密文。 因为是不可逆的,所以是无法通过密文推测出明文的内容,所以这个算...
  • wdscq1234
  • wdscq1234
  • 2016-10-15 11:59:16
  • 882

IPv6地址表示方法详解

IPv6是互联网协议的第六版;最初它在IETF的 IPng选取过程中胜出时称为互联网新一代网际协议(IPng),IPv6是被正式广泛使用的第二版互联网协议。 现有标准IPv4只支持大概40亿(4...
  • sdgihshdv
  • sdgihshdv
  • 2018-01-04 18:31:11
  • 1019

Libnids TCP会话重组分析

作者:geeksword 出处:http://onestraw.net/cybersecurity/libnids-tcp-assembly 声明:本文采用以下协议进行授权: 署名-非商用|CC ...
  • u013074465
  • u013074465
  • 2015-05-07 14:42:53
  • 2350

Linux route 中rt_hash 源码(转)

ip_route_input() --> rt_hash()#define rt_hash(daddr, saddr, idx)             /    rt_hash_code((__fo...
  • suifeng08
  • suifeng08
  • 2010-08-13 18:25:00
  • 458

Netfilter中的连接跟踪系统

呵呵,第一次翻译技术文章,还挺大家见谅。原作连接:netfilter tracking system 基于单一的报文头信息的过滤策略已经过时了。如今有状态防火墙提供了一种高级机制,让系统管理...
  • appletreesujie
  • appletreesujie
  • 2011-09-30 18:28:19
  • 4380

netfilter 链接跟踪机制与NAT原理

内核版本:2.6.12 1.链接跟踪 conntrack 1.1.netfilter框架 5个链: NF_IP_PRE_ROUTING:数据包进入路由表之前 NF_IP_LOCA...
  • qk1992919
  • qk1992919
  • 2016-04-14 09:48:29
  • 294
收藏助手
不良信息举报
您举报文章:linux内核netfilter连接跟踪的hash算法
举报原因:
原因补充:

(最多只允许输入30个字)