• conntrack最大数量


    在加载nf_conntrack模块的时候,可以通过参数hashsize控制conntrack的最大数量。

    module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint,
              &nf_conntrack_htable_size, 0600);
    
    • 1
    • 2

    如下,指定参数hashsize为1,系统计算出的conntrack最大数量为4096。

    # modprobe nf_conntrack hashsize=1
    # 
    # cat /proc/sys/net/netfilter/nf_conntrack_max
    4096
    
    • 1
    • 2
    • 3
    • 4

    处理函数中,模块参数hashsize只能在init_net命名空间设置。由于模块加载时nf_conntrack_hash为空,直接将hashsize的值赋予nf_conntrack_htable_size(1)。

    int nf_conntrack_set_hashsize(const char *val, const struct kernel_param *kp)
    {
        unsigned int hashsize;
        int rc;
    
        if (current->nsproxy->net_ns != &init_net)
            return -EOPNOTSUPP;
    
        /* On boot, we can set this without any fancy locking. */
        if (!nf_conntrack_hash)
            return param_set_uint(val, kp);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在模块初始化函数中,由函数nf_ct_alloc_hashtable将对nf_conntrack_htable_size值进行修正,最大conntrack数量设置为哈希大小的8倍,即512*8=4096。

    int nf_conntrack_init_start(void)
    {
        int max_factor = 8;
    
        nf_conntrack_hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size, 1);
        if (!nf_conntrack_hash)
            return -ENOMEM;
    
        nf_conntrack_max = max_factor * nf_conntrack_htable_size;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在函数nf_ct_alloc_hashtable中,将模块参数指定的hashsize(sizep),调整为一个页面可容纳的hlist_nulls_head结构的整数倍。即(PAGE_SIZE / sizeof(struct hlist_nulls_head))的整数倍。这样所分配的所有hlist_nulls_head结构将占用完整的页面。

    void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
    {
        struct hlist_nulls_head *hash;
        unsigned int nr_slots, i;
    
        if (*sizep > (UINT_MAX / sizeof(struct hlist_nulls_head)))
            return NULL;
     
        BUILD_BUG_ON(sizeof(struct hlist_nulls_head) != sizeof(struct hlist_head));
        nr_slots = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_nulls_head));
    
        hash = kvcalloc(nr_slots, sizeof(struct hlist_nulls_head), GFP_KERNEL);
    
        if (hash && nulls)
            for (i = 0; i < nr_slots; i++)
                INIT_HLIST_NULLS_HEAD(&hash[i], i);
    
        return hash; 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    按照PAGE_SIZE为4K,hlist_nulls_head结构大小为8字节,可得一个页面容纳512个此结构,如下nf_conntrack_buckets的值,512个哈希桶。

    # getconf PAGE_SIZE
    4096
    #
    # cat /proc/sys/net/netfilter/nf_conntrack_buckets 
    512
    #
    # cat /proc/sys/net/netfilter/nf_conntrack_max 
    4096
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    默认conntrack最大值

    如果在模块加载时没有指定hashsize参数,内核将根据内存大小计算哈希表的大小。nf_conntrack_htable_size等于总内存的1/16k,除以hlist_head结构体的大小。

    int nf_conntrack_init_start(void)
    {
        unsigned long nr_pages = totalram_pages();
        int max_factor = 8;
    
        if (!nf_conntrack_htable_size) {
            /* Idea from tcp.c: use 1/16384 of memory.
             * On i386: 32MB machine has 512 buckets.
             * >= 1GB machines have 16384 buckets.
             * >= 4GB machines have 65536 buckets.
             */
            nf_conntrack_htable_size
                = (((nr_pages << PAGE_SHIFT) / 16384)
                   / sizeof(struct hlist_head));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    对于1G内存,依据以上公式可得:1024 * 1024 * 1024 / 16384 / 8 = 16384; 对于4G内存,可得到哈希表大小为65536。以下规定当内存大于4G时,哈希大小固定为65536。而对于大于1G小于4G内存的情况,哈希大小固定使用16384。最后,nf_conntrack_htable_size的最小值为32。

    nf_conntrack_max为nf_conntrack_htable_size值的4倍。

            if (nr_pages > (4 * (1024 * 1024 * 1024 / PAGE_SIZE)))
                nf_conntrack_htable_size = 65536;
            else if (nr_pages > (1024 * 1024 * 1024 / PAGE_SIZE))
                nf_conntrack_htable_size = 16384;
            if (nf_conntrack_htable_size < 32)
                nf_conntrack_htable_size = 32;
    
            /* Use a max. factor of four by default to get the same max as
             * with the old struct list_heads. When a table size is given
             * we use the old value of 8 to avoid reducing the max.
             * entries. */
            max_factor = 4;
        }
    
        nf_conntrack_hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size, 1);
        if (!nf_conntrack_hash)
            return -ENOMEM;
    
        nf_conntrack_max = max_factor * nf_conntrack_htable_size;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    内核版本 5.10

  • 相关阅读:
    m1 rvm install 3.0.0 Error running ‘__rvm_make -j8‘
    二叉树 | 删除二叉树中的节点、修剪二叉树 | leecode刷题笔记
    基于VMware从零搭建Linux系统
    Nodejs核心模块之Events
    找不到vcruntime140.dll,无法继续执行代码,vcruntime140.dll怎么修复
    DeFi借贷重新洗牌 透过协议变化能找到哪些新趋势?
    java计算机毕业设计社区卫生预约挂号系统源码+系统+mysql数据库+lw文档+部署
    2022年12月 C/C++(六级)真题解析#中国电子学会#全国青少年软件编程等级考试
    【继RNN之后的一项技术】Transfomer 学习笔记
    WARING: UNPROTECTED PRIVATE KEY FILE!
  • 原文地址:https://blog.csdn.net/sinat_20184565/article/details/126694316