当前位置 : 主页 > 操作系统 > centos >

Linux协议栈优化之Netfilter分类conntrack

来源:互联网 收集:自由互联 发布时间:2022-06-20
首先,如果你不同意我以下的观点,本文就不必看了:如今内存不值钱,空间换时间很划算,要知道,一万年前的1秒和一万年后1秒是一样的,你要是觉得人们做的事情可能不同,但是

首先,如果你不同意我以下的观点,本文就不必看了:如今内存不值钱,空间换时间很划算,要知道,一万年前的1秒和一万年后1秒是一样的,你要是觉得人们做的事情可能不同,但是请记住,永远都会发生“安迪给你的被比尔拿走”之类的事情,对于你而言,什么都没有改变!
       虽然空间可以被拓展,但是要讲技巧。以下是一张截图,测试的是http服务器的常规性能,我依然使用相对值比较,因为我的电脑压不出真实性能,另外,为了 将网络影响降低,我使用了本地环回地址,我的目的是测试conntrack对新建连接数的影响,截图如下:
Linux协议栈优化之Netfilter分类conntrack_服务器如 果你稍微明白一些conntrack的原理,就会明白它的开销主要集中在两个方面,一个是查找开销,在内存不值钱的年代,可以通过设置很大的hash bucket来缓解,另外一个开销就是分配conn结构体内存的开销。如果在一台压力很大的设备上,短连接特别多,所有的conntrack将会在一张 hash表内,我们所能指望的就是针对一个五元组计算的hash值足够散列了,如果对于一些攻击流量,特别是当他研究了Linux计算conntrack hash值的算法后,他会构造很多hash一致的不同五元组的数据包,这会使得hash表的冲突链表过长,遍历开销过大,在当前的内核conntrack 模块实现中,这是无法避免的,因为所有鸡蛋都在一个篮子里面。现在换一个思路。
       将不同类的数据流分到不同的hash表中如何?也就是说将一张大表拆分成几张小表,或者说如果你真的不在乎内存的话,设置多张大表也行!那么剩下的问题就是将数据包进行分类了。可以有两种实现:
1.在RAW表中做一个模块
根据skb的特征设置其conntrack表索引,值得注意的是,为了避免同一个流分配到不同的hash表,match项必须是计算hash的元素,比如源/目标IP,源/目标端口,协议等。对于IP分片直接通过,不予考虑。
2.在MANGLE表中做一个优先级大于conntrack小于defrag的模块
这个就不多说了,和1一样,就是解决了IP分片的问题。
iptables规则如下:
iptables -t mangle -A PREROUTING -s 1.1.1.0/24 -j CONNMAP 2
以上规则将源IP为1.1.1.0/24段的数据包的conntrack设置在表2中。你也可以区分TCP协议和UDP协议,每一个协议一张表,这样就可以避免恶意UDP流量攻击问题。在加载模块的时候,你需要设置一个参数,即hash表的数量。
       为了快速测试效果,我依然是先将代码写死,设置了3张hash表,基于内核3.2.5,两个patch如下:
C文件patch:

diff -uNr linux-source-3.2/net/ipv4/netfilter/ipt_MASQUERADE.c linux-source-3.2.new/net/ipv4/netfilter/ipt_MASQUERADE.c --- linux-source-3.2/net/ipv4/netfilter/ipt_MASQUERADE.c        2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/ipv4/netfilter/ipt_MASQUERADE.c    2014-07-11 10:32:57.736666273 +0800 @@ -85,7 +85,7 @@                   mr->range[0].min, mr->range[0].max });           /* Hand modified range to generic setup. */ -       return nf_nat_setup_info(ct, &newrange, IP_NAT_MANIP_SRC); +       return nf_nat_setup_info(ct, &newrange, IP_NAT_MANIP_SRC, 0);  }    static int diff -uNr linux-source-3.2/net/ipv4/netfilter/ipt_NETMAP.c linux-source-3.2.new/net/ipv4/netfilter/ipt_NETMAP.c --- linux-source-3.2/net/ipv4/netfilter/ipt_NETMAP.c    2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/ipv4/netfilter/ipt_NETMAP.c        2014-07-11 10:35:14.976667434 +0800 @@ -67,7 +67,7 @@                   mr->range[0].min, mr->range[0].max });           /* Hand modified range to generic setup. */ -       return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum)); +       return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum), 0);  }    static struct xt_target netmap_tg_reg __read_mostly = { diff -uNr linux-source-3.2/net/ipv4/netfilter/ipt_REDIRECT.c linux-source-3.2.new/net/ipv4/netfilter/ipt_REDIRECT.c --- linux-source-3.2/net/ipv4/netfilter/ipt_REDIRECT.c  2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/ipv4/netfilter/ipt_REDIRECT.c      2014-07-11 10:36:45.760668202 +0800 @@ -82,7 +82,7 @@                   mr->range[0].min, mr->range[0].max });           /* Hand modified range to generic setup. */ -       return nf_nat_setup_info(ct, &newrange, IP_NAT_MANIP_DST); +       return nf_nat_setup_info(ct, &newrange, IP_NAT_MANIP_DST, 0);  }    static struct xt_target redirect_tg_reg __read_mostly = { diff -uNr linux-source-3.2/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c linux-source-3.2.new/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c --- linux-source-3.2/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c     2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c 2014-07-11 15:03:50.596093049 +0800 @@ -151,6 +151,12 @@                                       const struct net_device *out,                                       int (*okfn)(struct sk_buff *))  { +       struct iphdr *hdr = ip_hdr(skb); +       if (ipv4_is_loopback(hdr->saddr)||ipv4_is_loopback(hdr->daddr)) { +               skb->ij = 1; +       } else { +               skb->ij = 0; +       }         return nf_conntrack_in(dev_net(in), PF_INET, hooknum, skb);  }   @@ -160,6 +166,12 @@                                          const struct net_device *out,                                          int (*okfn)(struct sk_buff *))  { +       struct iphdr *hdr = ip_hdr(skb); +       if (ipv4_is_loopback(hdr->saddr)||ipv4_is_loopback(hdr->daddr)) { +               skb->ij = 1; +       } else { +               skb->ij = 0; +       }         /* root is playing with raw sockets. */         if (skb->len < sizeof(struct iphdr) ||             ip_hdrlen(skb) < sizeof(struct iphdr)) @@ -254,7 +266,7 @@  getorigdst(struct sock *sk, int optval, void __user *user, int *len)  {         const struct inet_sock *inet = inet_sk(sk); -       const struct nf_conntrack_tuple_hash *h; +       /*const struct nf_conntrack_tuple_hash *h;*/         struct nf_conntrack_tuple tuple;           memset(&tuple, 0, sizeof(tuple)); @@ -276,7 +288,7 @@                          *len, sizeof(struct sockaddr_in));                 return -EINVAL;         } - +/*         h = nf_conntrack_find_get(sock_net(sk), NF_CT_DEFAULT_ZONE, &tuple);         if (h) {                 struct sockaddr_in sin; @@ -297,6 +309,7 @@                 else                         return 0;         } +*/         pr_debug("SO_ORIGINAL_DST: Can't find %pI4/%u-%pI4/%u.\n",                  &tuple.src.u3.ip, ntohs(tuple.src.u.tcp.port),                  &tuple.dst.u3.ip, ntohs(tuple.dst.u.tcp.port)); diff -uNr linux-source-3.2/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c linux-source-3.2.new/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c --- linux-source-3.2/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c      2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c  2014-07-11 09:11:02.144624681 +0800 @@ -38,7 +38,7 @@              st->bucket < net->ct.htable_size;              st->bucket++) {                 n = rcu_dereference( -                       hlist_nulls_first_rcu(&net->ct.hash[st->bucket])); +                       hlist_nulls_first_rcu(&net->ct.hash[0][st->bucket]));                 if (!is_a_nulls(n))                         return n;         } @@ -58,7 +58,7 @@                                 return NULL;                 }                 head = rcu_dereference( -                       hlist_nulls_first_rcu(&net->ct.hash[st->bucket])); +                       hlist_nulls_first_rcu(&net->ct.hash[0][st->bucket]));         }         return head;  } diff -uNr linux-source-3.2/net/ipv4/netfilter/nf_conntrack_proto_icmp.c linux-source-3.2.new/net/ipv4/netfilter/nf_conntrack_proto_icmp.c --- linux-source-3.2/net/ipv4/netfilter/nf_conntrack_proto_icmp.c       2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/ipv4/netfilter/nf_conntrack_proto_icmp.c   2014-07-11 09:55:31.704647269 +0800 @@ -148,7 +148,7 @@           *ctinfo = IP_CT_RELATED;   -       h = nf_conntrack_find_get(net, zone, &innertuple); +       h = nf_conntrack_find_get(net, zone, &innertuple, skb->ij);         if (!h) {                 pr_debug("icmp_error_message: no match\n");                 return -NF_ACCEPT; diff -uNr linux-source-3.2/net/ipv4/netfilter/nf_nat_core.c linux-source-3.2.new/net/ipv4/netfilter/nf_nat_core.c --- linux-source-3.2/net/ipv4/netfilter/nf_nat_core.c   2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/ipv4/netfilter/nf_nat_core.c       2014-07-11 10:24:16.544661863 +0800 @@ -74,7 +74,7 @@         struct nf_conntrack_tuple reply;           nf_ct_invert_tuplepr(&reply, tuple); -       return nf_conntrack_tuple_taken(&reply, ignored_conntrack); +       return nf_conntrack_tuple_taken(&reply, ignored_conntrack, 0);  }  EXPORT_SYMBOL(nf_nat_used_tuple);   @@ -206,7 +206,7 @@                  const struct nf_conntrack_tuple *orig_tuple,                  const struct nf_nat_range *range,                  struct nf_conn *ct, -                enum nf_nat_manip_type maniptype) +                enum nf_nat_manip_type maniptype, int ij)  {         struct net *net = nf_ct_net(ct);         const struct nf_nat_protocol *proto; @@ -268,7 +268,7 @@  unsigned int  nf_nat_setup_info(struct nf_conn *ct,                   const struct nf_nat_range *range, -                 enum nf_nat_manip_type maniptype) +                 enum nf_nat_manip_type maniptype, int ij)  {         struct net *net = nf_ct_net(ct);         struct nf_conntrack_tuple curr_tuple, new_tuple; @@ -296,7 +296,7 @@         nf_ct_invert_tuplepr(&curr_tuple,                              &ct->tuplehash[IP_CT_DIR_REPLY].tuple);   -       get_unique_tuple(&new_tuple, &curr_tuple, range, ct, maniptype); +       get_unique_tuple(&new_tuple, &curr_tuple, range, ct, maniptype, ij);           if (!nf_ct_tuple_equal(&new_tuple, &curr_tuple)) {                 struct nf_conntrack_tuple reply; @@ -670,7 +670,7 @@         if (nf_nat_initialized(ct, manip))                 return -EEXIST;   -       return nf_nat_setup_info(ct, &range, manip); +       return nf_nat_setup_info(ct, &range, manip, 0);  }  #else  static int diff -uNr linux-source-3.2/net/ipv4/netfilter/nf_nat_h323.c linux-source-3.2.new/net/ipv4/netfilter/nf_nat_h323.c --- linux-source-3.2/net/ipv4/netfilter/nf_nat_h323.c   2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/ipv4/netfilter/nf_nat_h323.c       2014-07-11 10:08:16.712653742 +0800 @@ -411,14 +411,14 @@         /* Change src to where master sends to */         range.flags = IP_NAT_RANGE_MAP_IPS;         range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; -       nf_nat_setup_info(new, &range, IP_NAT_MANIP_SRC); +       nf_nat_setup_info(new, &range, IP_NAT_MANIP_SRC, 0);           /* For DST manip, map port here to where it's expected. */         range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);         range.min = range.max = this->saved_proto;         range.min_ip = range.max_ip =             new->master->tuplehash[!this->dir].tuple.src.u3.ip; -       nf_nat_setup_info(new, &range, IP_NAT_MANIP_DST); +       nf_nat_setup_info(new, &range, IP_NAT_MANIP_DST, 0);  }    /****************************************************************************/ @@ -504,13 +504,13 @@         /* Change src to where master sends to */         range.flags = IP_NAT_RANGE_MAP_IPS;         range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; -       nf_nat_setup_info(new, &range, IP_NAT_MANIP_SRC); +       nf_nat_setup_info(new, &range, IP_NAT_MANIP_SRC, 0);           /* For DST manip, map port here to where it's expected. */         range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);         range.min = range.max = this->saved_proto;         range.min_ip = range.max_ip = this->saved_ip; -       nf_nat_setup_info(new, &range, IP_NAT_MANIP_DST); +       nf_nat_setup_info(new, &range, IP_NAT_MANIP_DST, 0);  }    /****************************************************************************/ diff -uNr linux-source-3.2/net/ipv4/netfilter/nf_nat_helper.c linux-source-3.2.new/net/ipv4/netfilter/nf_nat_helper.c --- linux-source-3.2/net/ipv4/netfilter/nf_nat_helper.c 2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/ipv4/netfilter/nf_nat_helper.c     2014-07-11 10:08:55.008654066 +0800 @@ -439,13 +439,13 @@         range.flags = IP_NAT_RANGE_MAP_IPS;         range.min_ip = range.max_ip                 = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; -       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); +       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC, 0);           /* For DST manip, map port here to where it's expected. */         range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);         range.min = range.max = exp->saved_proto;         range.min_ip = range.max_ip                 = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip; -       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); +       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST, 0);  }  EXPORT_SYMBOL(nf_nat_follow_master); diff -uNr linux-source-3.2/net/ipv4/netfilter/nf_nat_pptp.c linux-source-3.2.new/net/ipv4/netfilter/nf_nat_pptp.c --- linux-source-3.2/net/ipv4/netfilter/nf_nat_pptp.c   2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/ipv4/netfilter/nf_nat_pptp.c       2014-07-11 10:08:35.424653900 +0800 @@ -95,7 +95,7 @@                 range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;                 range.min = range.max = exp->saved_proto;         } -       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); +       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC, 0);           /* For DST manip, map port here to where it's expected. */         range.flags = IP_NAT_RANGE_MAP_IPS; @@ -105,7 +105,7 @@                 range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED;                 range.min = range.max = exp->saved_proto;         } -       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); +       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST, 0);  }    /* outbound packets == from PNS to PAC */ diff -uNr linux-source-3.2/net/ipv4/netfilter/nf_nat_rule.c linux-source-3.2.new/net/ipv4/netfilter/nf_nat_rule.c --- linux-source-3.2/net/ipv4/netfilter/nf_nat_rule.c   2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/ipv4/netfilter/nf_nat_rule.c       2014-07-11 10:09:31.024654370 +0800 @@ -56,7 +56,7 @@                             ctinfo == IP_CT_RELATED_REPLY));         NF_CT_ASSERT(par->out != NULL);   -       return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC); +       return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC, 0);  }    static unsigned int @@ -74,7 +74,7 @@         /* Connection must be valid and new. */         NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));   -       return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST); +       return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST, 0);  }    static int ipt_snat_checkentry(const struct xt_tgchk_param *par) @@ -115,7 +115,7 @@                  &ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip :                  &ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip);   -       return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum)); +       return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum), 0);  }    int nf_nat_rule_find(struct sk_buff *skb, diff -uNr linux-source-3.2/net/ipv4/netfilter/nf_nat_sip.c linux-source-3.2.new/net/ipv4/netfilter/nf_nat_sip.c --- linux-source-3.2/net/ipv4/netfilter/nf_nat_sip.c    2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/ipv4/netfilter/nf_nat_sip.c        2014-07-11 10:07:40.744653437 +0800 @@ -259,7 +259,7 @@         range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED);         range.min = range.max = exp->saved_proto;         range.min_ip = range.max_ip = exp->saved_ip; -       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); +       nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST, 0);           /* Change src to where master sends to, but only if the connection          * actually came from the same source. */ @@ -268,7 +268,7 @@                 range.flags = IP_NAT_RANGE_MAP_IPS;                 range.min_ip = range.max_ip                         = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; -               nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); +               nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC, 0);         }  }   diff -uNr linux-source-3.2/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c linux-source-3.2.new/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c --- linux-source-3.2/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c     2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c 2014-07-11 09:12:04.320625207 +0800 @@ -165,7 +165,7 @@           *ctinfo = IP_CT_RELATED;   -       h = nf_conntrack_find_get(net, zone, &intuple); +       h = nf_conntrack_find_get(net, zone, &intuple, skb->ij);         if (!h) {                 pr_debug("icmpv6_error: no match\n");                 return -NF_ACCEPT; diff -uNr linux-source-3.2/net/netfilter/ipvs/ip_vs_nfct.c linux-source-3.2.new/net/netfilter/ipvs/ip_vs_nfct.c --- linux-source-3.2/net/netfilter/ipvs/ip_vs_nfct.c    2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/netfilter/ipvs/ip_vs_nfct.c        2014-07-11 11:10:42.224685433 +0800 @@ -270,7 +270,7 @@                 __func__, ARG_TUPLE(&tuple), ARG_CONN(cp));           h = nf_conntrack_find_get(ip_vs_conn_net(cp), NF_CT_DEFAULT_ZONE, -                                 &tuple); +                                 &tuple, 0);         if (h) {                 ct = nf_ct_tuplehash_to_ctrack(h);                 /* Show what happens instead of calling nf_ct_kill() */ diff -uNr linux-source-3.2/net/netfilter/nf_conntrack_core.c linux-source-3.2.new/net/netfilter/nf_conntrack_core.c --- linux-source-3.2/net/netfilter/nf_conntrack_core.c  2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/netfilter/nf_conntrack_core.c      2014-07-11 10:48:19.948674076 +0800 @@ -316,7 +316,7 @@   */  static struct nf_conntrack_tuple_hash *  ____nf_conntrack_find(struct net *net, u16 zone, -                     const struct nf_conntrack_tuple *tuple, u32 hash) +                     const struct nf_conntrack_tuple *tuple, u32 hash, int ij)  {         struct nf_conntrack_tuple_hash *h;         struct hlist_nulls_node *n; @@ -327,7 +327,7 @@          */         local_bh_disable();  begin: -       hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[bucket], hnnode) { +       hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[ij][bucket], hnnode) {                 if (nf_ct_tuple_equal(tuple, &h->tuple) &&                     nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)) == zone) {                         NF_CT_STAT_INC(net, found); @@ -352,24 +352,24 @@    struct nf_conntrack_tuple_hash *  __nf_conntrack_find(struct net *net, u16 zone, -                   const struct nf_conntrack_tuple *tuple) +                   const struct nf_conntrack_tuple *tuple, int ij)  {         return ____nf_conntrack_find(net, zone, tuple, -                                    hash_conntrack_raw(tuple, zone)); +                                    hash_conntrack_raw(tuple, zone), ij);  }  EXPORT_SYMBOL_GPL(__nf_conntrack_find);    /* Find a connection corresponding to a tuple. */  static struct nf_conntrack_tuple_hash *  __nf_conntrack_find_get(struct net *net, u16 zone, -                       const struct nf_conntrack_tuple *tuple, u32 hash) +                       const struct nf_conntrack_tuple *tuple, u32 hash, int ij)  {         struct nf_conntrack_tuple_hash *h;         struct nf_conn *ct;           rcu_read_lock();  begin: -       h = ____nf_conntrack_find(net, zone, tuple, hash); +       h = ____nf_conntrack_find(net, zone, tuple, hash, ij);         if (h) {                 ct = nf_ct_tuplehash_to_ctrack(h);                 if (unlikely(nf_ct_is_dying(ct) || @@ -390,26 +390,27 @@    struct nf_conntrack_tuple_hash *  nf_conntrack_find_get(struct net *net, u16 zone, -                     const struct nf_conntrack_tuple *tuple) +                     const struct nf_conntrack_tuple *tuple, int ij)  {         return __nf_conntrack_find_get(net, zone, tuple, -                                      hash_conntrack_raw(tuple, zone)); +                                      hash_conntrack_raw(tuple, zone), ij);  }  EXPORT_SYMBOL_GPL(nf_conntrack_find_get);    static void __nf_conntrack_hash_insert(struct nf_conn *ct,                                        unsigned int hash, -                                      unsigned int repl_hash) +                                      unsigned int repl_hash, +                                       int ij)  {         struct net *net = nf_ct_net(ct);           hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, -                          &net->ct.hash[hash]); +                          &net->ct.hash[ij][hash]);         hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode, -                          &net->ct.hash[repl_hash]); +                          &net->ct.hash[ij][repl_hash]);  }   -void nf_conntrack_hash_insert(struct nf_conn *ct) +void nf_conntrack_hash_insert(struct nf_conn *ct, int ij)  {         struct net *net = nf_ct_net(ct);         unsigned int hash, repl_hash; @@ -419,7 +420,7 @@         hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);         repl_hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_REPLY].tuple);   -       __nf_conntrack_hash_insert(ct, hash, repl_hash); +       __nf_conntrack_hash_insert(ct, hash, repl_hash, ij);  }  EXPORT_SYMBOL_GPL(nf_conntrack_hash_insert);   @@ -479,12 +480,12 @@         /* See if there's one in the list already, including reverse:            NAT could have grabbed it without realizing, since we're            not in the hash.  If there is, we lost race. */ -       hlist_nulls_for_each_entry(h, n, &net->ct.hash[hash], hnnode) +       hlist_nulls_for_each_entry(h, n, &net->ct.hash[skb->ij][hash], hnnode)                 if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,                                       &h->tuple) &&                     zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)))                         goto out; -       hlist_nulls_for_each_entry(h, n, &net->ct.hash[repl_hash], hnnode) +       hlist_nulls_for_each_entry(h, n, &net->ct.hash[skb->ij][repl_hash], hnnode)                 if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple,                                       &h->tuple) &&                     zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) @@ -514,7 +515,7 @@          * guarantee that no other CPU can find the conntrack before the above          * stores are visible.          */ -       __nf_conntrack_hash_insert(ct, hash, repl_hash); +       __nf_conntrack_hash_insert(ct, hash, repl_hash, skb->ij);         NF_CT_STAT_INC(net, insert);         spin_unlock_bh(&nf_conntrack_lock);   @@ -537,7 +538,7 @@     for NAT). */  int  nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, -                        const struct nf_conn *ignored_conntrack) +                        const struct nf_conn *ignored_conntrack, int ij)  {         struct net *net = nf_ct_net(ignored_conntrack);         struct nf_conntrack_tuple_hash *h; @@ -550,7 +551,7 @@          * least once for the stats anyway.          */         rcu_read_lock_bh(); -       hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { +       hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[ij][hash], hnnode) {                 ct = nf_ct_tuplehash_to_ctrack(h);                 if (ct != ignored_conntrack &&                     nf_ct_tuple_equal(tuple, &h->tuple) && @@ -571,7 +572,7 @@    /* There's a small race here where we may free a just-assured     connection.  Too bad: we're in trouble anyway. */ -static noinline int early_drop(struct net *net, unsigned int hash) +static noinline int early_drop(struct net *net, unsigned int hash, int ij)  {         /* Use oldest entry, which is roughly LRU */         struct nf_conntrack_tuple_hash *h; @@ -582,7 +583,7 @@           rcu_read_lock();         for (i = 0; i < net->ct.htable_size; i++) { -               hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], +               hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[ij][hash],                                          hnnode) {                         tmp = nf_ct_tuplehash_to_ctrack(h);                         if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) @@ -636,7 +637,7 @@  __nf_conntrack_alloc(struct net *net, u16 zone,                      const struct nf_conntrack_tuple *orig,                      const struct nf_conntrack_tuple *repl, -                    gfp_t gfp, u32 hash) +                    gfp_t gfp, u32 hash, int ij)  {         struct nf_conn *ct;   @@ -651,7 +652,7 @@           if (nf_conntrack_max &&             unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) { -               if (!early_drop(net, hash_bucket(hash, net))) { +               if (!early_drop(net, hash_bucket(hash, net), ij)) {                         atomic_dec(&net->ct.count);                         if (net_ratelimit())                                 printk(KERN_WARNING @@ -713,9 +714,9 @@  struct nf_conn *nf_conntrack_alloc(struct net *net, u16 zone,                                    const struct nf_conntrack_tuple *orig,                                    const struct nf_conntrack_tuple *repl, -                                  gfp_t gfp) +                                  gfp_t gfp, int ij)  { -       return __nf_conntrack_alloc(net, zone, orig, repl, gfp, 0); +       return __nf_conntrack_alloc(net, zone, orig, repl, gfp, 0, ij);  }  EXPORT_SYMBOL_GPL(nf_conntrack_alloc);   @@ -753,7 +754,7 @@         }           ct = __nf_conntrack_alloc(net, zone, tuple, &repl_tuple, GFP_ATOMIC, -                                 hash); +                                 hash, skb->ij);         if (IS_ERR(ct))                 return (struct nf_conntrack_tuple_hash *)ct;   @@ -840,7 +841,7 @@           /* look for tuple match */         hash = hash_conntrack_raw(&tuple, zone); -       h = __nf_conntrack_find_get(net, zone, &tuple, hash); +       h = __nf_conntrack_find_get(net, zone, &tuple, hash, skb->ij);         if (!h) {                 h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto,                                    skb, dataoff, hash); @@ -1170,7 +1171,7 @@           spin_lock_bh(&nf_conntrack_lock);         for (; *bucket < net->ct.htable_size; (*bucket)++) { -               hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) { +               hlist_nulls_for_each_entry(h, n, &net->ct.hash[0][*bucket], hnnode) {                         ct = nf_ct_tuplehash_to_ctrack(h);                         if (iter(ct, data))                                 goto found; @@ -1297,6 +1298,7 @@    static void nf_conntrack_cleanup_net(struct net *net)  { +       int i = 0;   i_see_dead_people:         nf_ct_iterate_cleanup(net, kill_all, NULL);         nf_ct_release_dying_list(net); @@ -1305,7 +1307,9 @@                 goto i_see_dead_people;         }   -       nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size); +       for (i = 0; i < 3; i++) { +               nf_ct_free_hashtable(net->ct.hash[i], net->ct.htable_size); +       }         nf_conntrack_ecache_fini(net);         nf_conntrack_tstamp_fini(net);         nf_conntrack_acct_fini(net); @@ -1364,7 +1368,7 @@  {         int i, bucket;         unsigned int hashsize, old_size; -       struct hlist_nulls_head *hash, *old_hash; +       struct hlist_nulls_head *hash[3], *old_hash[3];         struct nf_conntrack_tuple_hash *h;         struct nf_conn *ct;   @@ -1378,10 +1382,19 @@         hashsize = simple_strtoul(val, NULL, 0);         if (!hashsize)                 return -EINVAL; - -       hash = nf_ct_alloc_hashtable(&hashsize, 1); -       if (!hash) -               return -ENOMEM; +       { +               int k = 0; +               for (k = 0; k < 3; k++) { +                       hash[k] = nf_ct_alloc_hashtable(&hashsize, 1); +                       if (!hash[k]) { +                               int j = 0; +                               for (j = 0; j < k; j++) { +                                       //free hash[j]; +                               } +                               return -ENOMEM; +                       } +               } +       }           /* Lookups in the old hash might happen in parallel, which means we          * might get false negatives during connection lookup. New connections @@ -1390,24 +1403,38 @@          */         spin_lock_bh(&nf_conntrack_lock);         for (i = 0; i < init_net.ct.htable_size; i++) { -               while (!hlist_nulls_empty(&init_net.ct.hash[i])) { -                       h = hlist_nulls_entry(init_net.ct.hash[i].first, +               int k = 0; +               for (k = 0; k < 3; k++) { +               while (!hlist_nulls_empty(&init_net.ct.hash[k][i])) { +                       h = hlist_nulls_entry(init_net.ct.hash[k][i].first,                                         struct nf_conntrack_tuple_hash, hnnode);                         ct = nf_ct_tuplehash_to_ctrack(h);                         hlist_nulls_del_rcu(&h->hnnode);                         bucket = __hash_conntrack(&h->tuple, nf_ct_zone(ct),                                                   hashsize); -                       hlist_nulls_add_head_rcu(&h->hnnode, &hash[bucket]); +                       hlist_nulls_add_head_rcu(&h->hnnode, &hash[k][bucket]); +               }                 }         }         old_size = init_net.ct.htable_size; -       old_hash = init_net.ct.hash; +       old_hash[0] = init_net.ct.hash[0]; +       old_hash[1] = init_net.ct.hash[1]; +       old_hash[2] = init_net.ct.hash[2];           init_net.ct.htable_size = nf_conntrack_htable_size = hashsize; -       init_net.ct.hash = hash; +       { +               int k = 0; +               for (k = 0; k < 3; k++) { +                       init_net.ct.hash[k] = hash[k]; +               } +       }         spin_unlock_bh(&nf_conntrack_lock); - -       nf_ct_free_hashtable(old_hash, old_size); +       { +               int k = 0; +               for (k = 0; k < 3; k++) { +                       nf_ct_free_hashtable(old_hash[k], old_size); +               } +       }         return 0;  }  EXPORT_SYMBOL_GPL(nf_conntrack_set_hashsize); @@ -1494,6 +1521,7 @@  static int nf_conntrack_init_net(struct net *net)  {         int ret; +       int i = 0;           atomic_set(&net->ct.count, 0);         INIT_HLIST_NULLS_HEAD(&net->ct.unconfirmed, UNCONFIRMED_NULLS_VAL); @@ -1520,11 +1548,13 @@         }           net->ct.htable_size = nf_conntrack_htable_size; -       net->ct.hash = nf_ct_alloc_hashtable(&net->ct.htable_size, 1); -       if (!net->ct.hash) { -               ret = -ENOMEM; -               printk(KERN_ERR "Unable to create nf_conntrack_hash\n"); -               goto err_hash; +       for (i = 0; i < 3; i++) { +               net->ct.hash[i] = nf_ct_alloc_hashtable(&net->ct.htable_size, 1); +               if (!net->ct.hash[i]) { +                       ret = -ENOMEM; +                       printk(KERN_ERR "Unable to create nf_conntrack_hash\n"); +                       goto err_hash; +               }         }         ret = nf_conntrack_expect_init(net);         if (ret < 0) @@ -1548,7 +1578,9 @@  err_acct:         nf_conntrack_expect_fini(net);  err_expect: -       nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size); +       for (i = 0; i < 3; i++) { +               nf_ct_free_hashtable(net->ct.hash[i], net->ct.htable_size); +       }  err_hash:         kmem_cache_destroy(net->ct.nf_conntrack_cachep);  err_cache: diff -uNr linux-source-3.2/net/netfilter/nf_conntrack_helper.c linux-source-3.2.new/net/netfilter/nf_conntrack_helper.c --- linux-source-3.2/net/netfilter/nf_conntrack_helper.c        2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/netfilter/nf_conntrack_helper.c    2014-07-11 10:57:25.424678691 +0800 @@ -227,7 +227,7 @@         hlist_nulls_for_each_entry(h, nn, &net->ct.unconfirmed, hnnode)                 unhelp(h, me);         for (i = 0; i < net->ct.htable_size; i++) { -               hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode) +               hlist_nulls_for_each_entry(h, nn, &net->ct.hash[0][i], hnnode)                         unhelp(h, me);         }  } diff -uNr linux-source-3.2/net/netfilter/nf_conntrack_netlink.c linux-source-3.2.new/net/netfilter/nf_conntrack_netlink.c --- linux-source-3.2/net/netfilter/nf_conntrack_netlink.c       2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/netfilter/nf_conntrack_netlink.c   2014-07-11 11:02:54.168681473 +0800 @@ -692,7 +692,7 @@         last = (struct nf_conn *)cb->args[1];         for (; cb->args[0] < net->ct.htable_size; cb->args[0]++) {  restart: -               hlist_nulls_for_each_entry(h, n, &net->ct.hash[cb->args[0]], +               hlist_nulls_for_each_entry(h, n, &net->ct.hash[0][cb->args[0]],                                          hnnode) {                         if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)                                 continue; @@ -920,7 +920,7 @@         if (err < 0)                 return err;   -       h = nf_conntrack_find_get(net, zone, &tuple); +       h = nf_conntrack_find_get(net, zone, &tuple, 0);         if (!h)                 return -ENOENT;   @@ -986,7 +986,7 @@         if (err < 0)                 return err;   -       h = nf_conntrack_find_get(net, zone, &tuple); +       h = nf_conntrack_find_get(net, zone, &tuple, skb->ij);         if (!h)                 return -ENOENT;   @@ -1336,7 +1336,7 @@         struct nf_conntrack_helper *helper;         struct nf_conn_tstamp *tstamp;   -       ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC); +       ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC, 0);         if (IS_ERR(ct))                 return ERR_PTR(-ENOMEM);   @@ -1446,7 +1446,7 @@                 if (err < 0)                         goto err2;   -               master_h = nf_conntrack_find_get(net, zone, &master); +               master_h = nf_conntrack_find_get(net, zone, &master, 0);                 if (master_h == NULL) {                         err = -ENOENT;                         goto err2; @@ -1460,7 +1460,7 @@                 tstamp->start = ktime_to_ns(ktime_get_real());           add_timer(&ct->timeout); -       nf_conntrack_hash_insert(ct); +       nf_conntrack_hash_insert(ct, 0);         rcu_read_unlock();           return ct; @@ -1503,9 +1503,9 @@           spin_lock_bh(&nf_conntrack_lock);         if (cda[CTA_TUPLE_ORIG]) -               h = __nf_conntrack_find(net, zone, &otuple); +               h = __nf_conntrack_find(net, zone, &otuple, 0);         else if (cda[CTA_TUPLE_REPLY]) -               h = __nf_conntrack_find(net, zone, &rtuple); +               h = __nf_conntrack_find(net, zone, &rtuple, 0);           if (h == NULL) {                 err = -ENOENT; @@ -2020,7 +2020,7 @@                 return err;           /* Look for master conntrack of this expectation */ -       h = nf_conntrack_find_get(net, zone, &master_tuple); +       h = nf_conntrack_find_get(net, zone, &master_tuple, 0);         if (!h)                 return -ENOENT;         ct = nf_ct_tuplehash_to_ctrack(h); diff -uNr linux-source-3.2/net/netfilter/nf_conntrack_pptp.c linux-source-3.2.new/net/netfilter/nf_conntrack_pptp.c --- linux-source-3.2/net/netfilter/nf_conntrack_pptp.c  2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/netfilter/nf_conntrack_pptp.c      2014-07-11 11:04:11.824682130 +0800 @@ -148,7 +148,7 @@         pr_debug("trying to timeout ct or exp for tuple ");         nf_ct_dump_tuple(t);   -       h = nf_conntrack_find_get(net, zone, t); +       h = nf_conntrack_find_get(net, zone, t, 0);         if (h)  {                 sibling = nf_ct_tuplehash_to_ctrack(h);                 pr_debug("setting timeout of conntrack %p to 0\n", sibling); diff -uNr linux-source-3.2/net/netfilter/nf_conntrack_standalone.c linux-source-3.2.new/net/netfilter/nf_conntrack_standalone.c --- linux-source-3.2/net/netfilter/nf_conntrack_standalone.c    2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/netfilter/nf_conntrack_standalone.c        2014-07-11 10:56:08.276678039 +0800 @@ -59,7 +59,7 @@         for (st->bucket = 0;              st->bucket < net->ct.htable_size;              st->bucket++) { -               n = rcu_dereference(hlist_nulls_first_rcu(&net->ct.hash[st->bucket])); +               n = rcu_dereference(hlist_nulls_first_rcu(&net->ct.hash[0][st->bucket]));                 if (!is_a_nulls(n))                         return n;         } @@ -80,7 +80,7 @@                 }                 head = rcu_dereference(                                 hlist_nulls_first_rcu( -                                       &net->ct.hash[st->bucket])); +                                       &net->ct.hash[0][st->bucket]));         }         return head;  } diff -uNr linux-source-3.2/net/netfilter/xt_connlimit.c linux-source-3.2.new/net/netfilter/xt_connlimit.c --- linux-source-3.2/net/netfilter/xt_connlimit.c       2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/netfilter/xt_connlimit.c   2014-07-11 11:07:55.712684024 +0800 @@ -117,7 +117,7 @@         /* check the saved connections */         hlist_for_each_entry_safe(conn, pos, n, hash, node) {                 found    = nf_conntrack_find_get(net, NF_CT_DEFAULT_ZONE, -                                                &conn->tuple); +                                                &conn->tuple, 0);                 found_ct = NULL;                   if (found != NULL) diff -uNr linux-source-3.2/net/netfilter/xt_CT.c linux-source-3.2.new/net/netfilter/xt_CT.c --- linux-source-3.2/net/netfilter/xt_CT.c      2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/net/netfilter/xt_CT.c  2014-07-11 11:06:38.648683372 +0800 @@ -81,7 +81,7 @@                 goto err1;           memset(&t, 0, sizeof(t)); -       ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL); +       ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL, 0);         ret = PTR_ERR(ct);         if (IS_ERR(ct))                 goto err2; H文件patch: diff -uNr linux-source-3.2/include/linux/skbuff.h linux-source-3.2.new/include/linux/skbuff.h --- linux-source-3.2/include/linux/skbuff.h     2014-02-01 21:18:39.000000000 +0800 +++ linux-source-3.2.new/include/linux/skbuff.h 2014-07-11 07:00:38.696558485 +0800 @@ -474,6 +474,7 @@         unsigned char           *head,                                 *data;         unsigned int            truesize; +       int                     ij;         atomic_t                users;  };   diff -uNr linux-source-3.2/include/linux/version.h linux-source-3.2.new/include/linux/version.h --- linux-source-3.2/include/linux/version.h    1970-01-01 08:00:00.000000000 +0800 +++ linux-source-3.2.new/include/linux/version.h        2014-07-11 07:01:03.972558699 +0800 @@ -0,0 +1,2 @@ +#define LINUX_VERSION_CODE 197174 +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) diff -uNr linux-source-3.2/include/net/netfilter/nf_conntrack_core.h linux-source-3.2.new/include/net/netfilter/nf_conntrack_core.h --- linux-source-3.2/include/net/netfilter/nf_conntrack_core.h  2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/include/net/netfilter/nf_conntrack_core.h      2014-07-11 08:59:04.872618612 +0800 @@ -50,7 +50,7 @@  /* Find a connection corresponding to a tuple. */  extern struct nf_conntrack_tuple_hash *  nf_conntrack_find_get(struct net *net, u16 zone, -                     const struct nf_conntrack_tuple *tuple); +                     const struct nf_conntrack_tuple *tuple, int ij);    extern int __nf_conntrack_confirm(struct sk_buff *skb);   diff -uNr linux-source-3.2/include/net/netfilter/nf_conntrack.h linux-source-3.2.new/include/net/netfilter/nf_conntrack.h --- linux-source-3.2/include/net/netfilter/nf_conntrack.h       2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/include/net/netfilter/nf_conntrack.h   2014-07-11 09:05:35.412621916 +0800 @@ -176,7 +176,7 @@     conntrack). */  extern int  nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, -                        const struct nf_conn *ignored_conntrack); +                        const struct nf_conn *ignored_conntrack, int ij);    /* Return conntrack_info and tuple hash for given skb. */  static inline struct nf_conn * @@ -207,9 +207,9 @@    extern struct nf_conntrack_tuple_hash *  __nf_conntrack_find(struct net *net, u16 zone, -                   const struct nf_conntrack_tuple *tuple); +                   const struct nf_conntrack_tuple *tuple, int ij);   -extern void nf_conntrack_hash_insert(struct nf_conn *ct); +extern void nf_conntrack_hash_insert(struct nf_conn *ct, int ij);  extern void nf_ct_delete_from_lists(struct nf_conn *ct);  extern void nf_ct_insert_dying_list(struct nf_conn *ct);   @@ -284,7 +284,7 @@  nf_conntrack_alloc(struct net *net, u16 zone,                    const struct nf_conntrack_tuple *orig,                    const struct nf_conntrack_tuple *repl, -                  gfp_t gfp); +                  gfp_t gfp, int ij);    static inline int nf_ct_is_template(const struct nf_conn *ct)  { diff -uNr linux-source-3.2/include/net/netfilter/nf_nat.h linux-source-3.2.new/include/net/netfilter/nf_nat.h --- linux-source-3.2/include/net/netfilter/nf_nat.h     2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/include/net/netfilter/nf_nat.h 2014-07-11 10:05:22.568652268 +0800 @@ -53,7 +53,7 @@  /* Set up the info structure to map into this range. */  extern unsigned int nf_nat_setup_info(struct nf_conn *ct,                                       const struct nf_nat_range *range, -                                     enum nf_nat_manip_type maniptype); +                                     enum nf_nat_manip_type maniptype, int ij);    /* Is this tuple already taken? (not by us)*/  extern int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple, diff -uNr linux-source-3.2/include/net/netns/conntrack.h linux-source-3.2.new/include/net/netns/conntrack.h --- linux-source-3.2/include/net/netns/conntrack.h      2014-01-03 12:33:36.000000000 +0800 +++ linux-source-3.2.new/include/net/netns/conntrack.h  2014-07-11 08:56:06.816617105 +0800 @@ -13,7 +13,7 @@         unsigned int            expect_count;         unsigned int            htable_size;         struct kmem_cache       *nf_conntrack_cachep; -       struct hlist_nulls_head *hash; +       struct hlist_nulls_head *hash[3];         struct hlist_head       *expect_hash;         struct hlist_nulls_head unconfirmed;         struct hlist_nulls_head dying;




重新编译内核之后,效果十分可观,按照下面的脚本加入巨量的conntrack也丝毫不会影响最大连接数:

for((i=1;i<220;i++));do for((j=1;j<254;j++));do \ conntrack -I conntrack -s 172.129.$j.$i -d $j.$i.192.$j -p udp -t 4000  --sport 245 --dport 2001;\ conntrack -I conntrack -s 192.13.$i.$j -d $i.$j.24.19 -p tcp --state ESTABLISHED -t 4000  --sport 67 --dport 505;\ conntrack -I conntrack -s 172.129.$j.$i -d $j.$i.192.$j -p icmp -t 4000;\ done;done >/dev/null 2>&1


除了分了多张hash之外,另外的好处在于锁的粒度变细了,每次在操作conntrack的时候只需要锁住和自己相关的hash表的 锁即可,当然,在本次的优化中没有涉及这一点。和ipset结合起来就更猛了,本身ipset就可以定义一个集合,而该集合则可以用来计算 conntrack的hash值,多表版本的conntrack和ipset结合,这在效果上不就是多级hash表吗?而且表面上还是iptables配 置的。


上一篇:Zabbix安装(四):Zabbix Agent For Linux
下一篇:没有了
网友评论