概述
目录
1 连接跟踪模块概述
2 核心初始化入口 module_init(nf_conntrack_standalone_init);
2.1 创建/proc/net/nf_conntrack只读文件 nf_conntrack_standalone_init_proc()
2.2 注册 /proc/sys/ 下相关文件
3 核心初始化 nf_conntrack_init()
3.1 hash表大小计算、L3L4协议栈模块、helper模块初始化
3.1.1 L3L4协议栈模块初始化
3.1.2 helper 模块初始化
3.2 hash表初始化、期望连接子模块初始化
3.2.1 期望连接子模块初始化
1 连接跟踪模块概述
连接跟踪模块的初始化过程分别在三个地方进行:
- 一个用于创建连接跟踪项与期望连接项相关的slab缓存;
- 一个用于注册连接跟踪模块相关的hook回调函数;
- 一个用于注册连接跟踪中协议相关的变量。
连接跟踪模块的意义:
- 连接跟踪模块的helper结构能够实现期望连接的建立以及相关协议的ALG功能。
- 连接跟踪为NAT或者状态防火墙的实现提供了依据
2 核心初始化入口 module_init(nf_conntrack_standalone_init);
nf_conntrack_standalone_init() 除了在/proc文件系统下面创建一些节点外,核心的初始化过程都是调用nf_conntrack_init()完成的。
static int nf_conntrack_net_init(struct net *net)
{
int ret;
//连接跟踪子系统的核心初始化过程
ret = nf_conntrack_init(net);
if (ret < 0)
goto out_init;
ret = nf_conntrack_standalone_init_proc(net);
if (ret < 0)
goto out_proc;
net->ct.sysctl_checksum = 1;
net->ct.sysctl_log_invalid = 0;
ret = nf_conntrack_standalone_init_sysctl(net);
if (ret < 0)
goto out_sysctl;
return 0;
out_sysctl:
nf_conntrack_standalone_fini_proc(net);
out_proc:
nf_conntrack_cleanup(net);
out_init:
return ret;
}
static void nf_conntrack_net_exit(struct net *net)
{
nf_conntrack_standalone_fini_sysctl(net);
nf_conntrack_standalone_fini_proc(net);
nf_conntrack_cleanup(net);
}
static struct pernet_operations nf_conntrack_net_ops = {
.init = nf_conntrack_net_init,
.exit = nf_conntrack_net_exit,
};
static int __init nf_conntrack_standalone_init(void)
{
return register_pernet_subsys(&nf_conntrack_net_ops);
}
static void __exit nf_conntrack_standalone_fini(void)
{
unregister_pernet_subsys(&nf_conntrack_net_ops);
}
module_init(nf_conntrack_standalone_init);
module_exit(nf_conntrack_standalone_fini);
2.1 创建/proc/net/nf_conntrack只读文件 nf_conntrack_standalone_init_proc()
static int nf_conntrack_standalone_init_proc(struct net *net)
{
struct proc_dir_entry *pde;
//创建/proc/net/nf_conntrack文件,该文件只读,
//读取该文件可以获取当前内核中跟踪的所有连接的信息
pde = proc_net_fops_create(net, "nf_conntrack", 0440, &ct_file_ops);
if (!pde)
goto out_nf_conntrack;
//创建/proc/net/stat/nf_conntrack文件,获取连接跟踪子系统的统计信息
pde = proc_create("nf_conntrack", S_IRUGO, net->proc_net_stat,
&ct_cpu_seq_fops);
if (!pde)
goto out_stat_nf_conntrack;
return 0;
out_stat_nf_conntrack:
proc_net_remove(net, "nf_conntrack");
out_nf_conntrack:
return -ENOMEM;
}
2.2 注册 /proc/sys/ 下相关文件
static int nf_conntrack_standalone_init_sysctl(struct net *net)
{
struct ctl_table *table;
//在/proc/sys/net/netfilter子目录,暴露一部分内核变量给用户态
if (net_eq(net, &init_net)) {
nf_ct_netfilter_header =
register_sysctl_paths(nf_ct_path, nf_ct_netfilter_table);
if (!nf_ct_netfilter_header)
goto out;
}
table = kmemdup(nf_ct_sysctl_table, sizeof(nf_ct_sysctl_table),
GFP_KERNEL);
if (!table)
goto out_kmemdup;
table[1].data = &net->ct.count;
table[3].data = &net->ct.sysctl_checksum;
table[4].data = &net->ct.sysctl_log_invalid;
net->ct.sysctl_header = register_net_sysctl_table(net,
nf_net_netfilter_sysctl_path, table);
if (!net->ct.sysctl_header)
goto out_unregister_netfilter;
return 0;
out_unregister_netfilter:
kfree(table);
out_kmemdup:
if (net_eq(net, &init_net))
unregister_sysctl_table(nf_ct_netfilter_header);
out:
printk("nf_conntrack: can't register to sysctl.n");
return -ENOMEM;
}
3 核心初始化 nf_conntrack_init()
该接口的核心功能:
- 设置nf_conntrack_htable_size、nf_conntrack_max的值;
- 为 nf_conntrack_hash 申请内存并初始化;
- 为连接跟踪项与期望连接跟踪项创建slab缓存。
- 初始化协议栈管理子模块、期望连接子模块、helper子模块
int nf_conntrack_init(struct net *net)
{
int ret;
if (net_eq(net, &init_net)) {
ret = nf_conntrack_init_init_net();
if (ret < 0)
goto out_init_net;
}
ret = nf_conntrack_init_net(net);
if (ret < 0)
goto out_net;
if (net_eq(net, &init_net)) {
/* For use by REJECT target */
rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);
rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
}
return 0;
out_net:
if (net_eq(net, &init_net))
nf_conntrack_cleanup_init_net();
out_init_net:
return ret;
}
3.1 hash表大小计算、L3L4协议栈模块、helper模块初始化
static int nf_conntrack_init_init_net(void)
{
int max_factor = 8;
int ret;
/* Idea from tcp.c: use 1/16384 of memory. On i386: 32MB
* machine has 512 buckets. >= 1GB machines have 16384 buckets. */
/* 当nf_conntrack_htable_size的值没有设置时,则在内存小于1GB时,
使用内存的1/16384作为hash数组的最大值;在内存大于1GB时
则最大hash数组的值为8192*/
if (!nf_conntrack_htable_size) {
nf_conntrack_htable_size
= (((num_physpages << PAGE_SHIFT) / 16384)
/ sizeof(struct hlist_head));
if (num_physpages > (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_max的值,即连接跟踪项的最大值。
该值取决于nf_conntrack_hash[]数组的最大值,即为
nf_conntrack_htable_size的8倍。*/
nf_conntrack_max = max_factor * nf_conntrack_htable_size;
...
//为连接跟踪信息块struct nf_conn创建高速缓存
nf_conntrack_cachep = kmem_cache_create("nf_conntrack",
sizeof(struct nf_conn),
0, 0, NULL);
if (!nf_conntrack_cachep) {
printk(KERN_ERR "Unable to create nf_conn slab cachen");
ret = -ENOMEM;
goto err_cache;
}
//初始化协议管理子模块
ret = nf_conntrack_proto_init();
if (ret < 0)
goto err_proto;
//初始化helper子模块
ret = nf_conntrack_helper_init();
if (ret < 0)
goto err_helper;
return 0;
...
}
3.1.1 L3L4协议栈模块初始化
参见xxx
3.1.2 helper 模块初始化
参见xxxx
3.2 hash表初始化、期望连接子模块初始化
static int nf_conntrack_init_net(struct net *net)
{
int ret;
atomic_set(&net->ct.count, 0);
INIT_HLIST_HEAD(&net->ct.unconfirmed);
net->ct.stat = alloc_percpu(struct ip_conntrack_stat);
if (!net->ct.stat) {
ret = -ENOMEM;
goto err_stat;
}
ret = nf_conntrack_ecache_init(net);
if (ret < 0)
goto err_ecache;
//hash链表的初始化,申请 nf_conntrack_htable_size 个hash链表
net->ct.hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size,
&net->ct.hash_vmalloc);
if (!net->ct.hash) {
ret = -ENOMEM;
printk(KERN_ERR "Unable to create nf_conntrack_hashn");
goto err_hash;
}
//初始化期望连接子模块
ret = nf_conntrack_expect_init(net);
if (ret < 0)
goto err_expect;
ret = nf_conntrack_acct_init(net);
if (ret < 0)
goto err_acct;
/* Set up fake conntrack:
- to never be deleted, not in any hashes */
#ifdef CONFIG_NET_NS
nf_conntrack_untracked.ct_net = &init_net;
#endif
atomic_set(&nf_conntrack_untracked.ct_general.use, 1);
/* - and look it like as a confirmed connection */
set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status);
return 0;
....
}
3.2.1 期望连接子模块初始化
参见xxx
最后
以上就是俏皮枕头为你收集整理的linux内核协议栈 netfilter 之连接跟踪子系统初始化1 连接跟踪模块概述2 核心初始化入口 module_init(nf_conntrack_standalone_init);3 核心初始化 nf_conntrack_init()的全部内容,希望文章能够帮你解决linux内核协议栈 netfilter 之连接跟踪子系统初始化1 连接跟踪模块概述2 核心初始化入口 module_init(nf_conntrack_standalone_init);3 核心初始化 nf_conntrack_init()所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复