IPVS负载均衡(六)浅析ip_vs_core.c
来源:互联网 发布:qemu-ga windows 1053 编辑:程序博客网 时间:2024/05/17 06:44
IPVS负载均衡(六)浅析ip_vs_core.c
ip_vs_core.c
先从linux内核module_init和module_exit开始。
module_init
函数:ip_vs_init
函数原型:static int __init ip_vs_init(void)
初始化ip_vs模块所需的各种
/* * Initialize IP Virtual Server */static int __init ip_vs_init(void){ int ret; ret = ip_vs_control_init(); if (ret < 0) { pr_err("can't setup control.\n"); goto exit; } ip_vs_protocol_init(); ret = ip_vs_conn_init(); if (ret < 0) { pr_err("can't setup connection table.\n"); goto cleanup_protocol; } ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */ if (ret < 0) goto cleanup_conn; ret = register_pernet_device(&ipvs_core_dev_ops); if (ret < 0) goto cleanup_sub; ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); if (ret < 0) { pr_err("can't register hooks.\n"); goto cleanup_dev; } ret = ip_vs_register_nl_ioctl(); if (ret < 0) { pr_err("can't register netlink/ioctl.\n"); goto cleanup_hooks; } pr_info("ipvs loaded.\n"); return ret;cleanup_hooks: nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));cleanup_dev: unregister_pernet_device(&ipvs_core_dev_ops);cleanup_sub: unregister_pernet_subsys(&ipvs_core_ops);cleanup_conn: ip_vs_conn_cleanup();cleanup_protocol: ip_vs_protocol_cleanup(); ip_vs_control_cleanup();exit: return ret;}
主要调用了:
->ip_vs_control_init->ip_vs_protocol_init,协议所需初始化->ip_vs_conn_init,链接管理初始化->register_pernet_subsys->register_pernet_device->nf_register_hooks,注册netfilter钩子函数,后续代码流程会从这里开始->ip_vs_register_nl_ioctl
其中跟IPVS主要流程最相关的是nf_register_hooks、ip_vs_protocol_init、ip_vs_conn_init,后续会主要从nf_register_hooks这里–在netfilter上注册的钩子函数上梳理主干流程
module_exit
函数:ip_vs_cleanup
函数原型:static void __exit ip_vs_cleanup(void)
卸载ip_vs模块,释放占用的资源等操作
static void __exit ip_vs_cleanup(void){ ip_vs_unregister_nl_ioctl(); nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); unregister_pernet_device(&ipvs_core_dev_ops); unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ ip_vs_conn_cleanup(); ip_vs_protocol_cleanup(); ip_vs_control_cleanup(); pr_info("ipvs unloaded.\n");}
主要调用:
->ip_vs_unregister_nl_ioctl->nf_unregister_hooks->unregister_pernet_device->unregister_pernet_subsys->ip_vs_conn_cleanup->ip_vs_protocol_cleanup->ip_vs_control_cleanup
可以注意到,ip_vs_cleanup资源释放顺序,与ip_vs_init申请资源顺序刚好相反;且与ip_vs_init中的出错处理部分顺序基本相同。
看完模块注册去注册流程,那么后面则开始寻找
nf_register_hooks钩子函数
通过nf_register_hooks注册的钩子函数进一步梳理代码流程
ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops));
ip_vs_ops的定义
static struct nf_hook_ops ip_vs_ops[] __read_mostly = { /* After packet filtering, change source only for VS/NAT */ { .hook = ip_vs_reply4, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_NAT_SRC - 2, }, /* After packet filtering, forward packet through VS/DR, VS/TUN, * or VS/NAT(change destination), so that filtering rules can be * applied to IPVS. */ { .hook = ip_vs_remote_request4, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_NAT_SRC - 1, }, /* Before ip_vs_in, change source only for VS/NAT */ { .hook = ip_vs_local_reply4, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_NAT_DST + 1, }, /* After mangle, schedule and forward local requests */ { .hook = ip_vs_local_request4, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP_PRI_NAT_DST + 2, }, /* After packet filtering (but before ip_vs_out_icmp), catch icmp * destined for 0.0.0.0/0, which is for incoming IPVS connections */ { .hook = ip_vs_forward_icmp, .pf = NFPROTO_IPV4, .hooknum = NF_INET_FORWARD, .priority = 99, }, /* After packet filtering, change source only for VS/NAT */ { .hook = ip_vs_reply4, .pf = NFPROTO_IPV4, .hooknum = NF_INET_FORWARD, .priority = 100, },#ifdef CONFIG_IP_VS_IPV6 /* After packet filtering, change source only for VS/NAT */ { .hook = ip_vs_reply6, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP6_PRI_NAT_SRC - 2, }, /* After packet filtering, forward packet through VS/DR, VS/TUN, * or VS/NAT(change destination), so that filtering rules can be * applied to IPVS. */ { .hook = ip_vs_remote_request6, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP6_PRI_NAT_SRC - 1, }, /* Before ip_vs_in, change source only for VS/NAT */ { .hook = ip_vs_local_reply6, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP6_PRI_NAT_DST + 1, }, /* After mangle, schedule and forward local requests */ { .hook = ip_vs_local_request6, .pf = NFPROTO_IPV6, .hooknum = NF_INET_LOCAL_OUT, .priority = NF_IP6_PRI_NAT_DST + 2, }, /* After packet filtering (but before ip_vs_out_icmp), catch icmp * destined for 0.0.0.0/0, which is for incoming IPVS connections */ { .hook = ip_vs_forward_icmp_v6, .pf = NFPROTO_IPV6, .hooknum = NF_INET_FORWARD, .priority = 99, }, /* After packet filtering, change source only for VS/NAT */ { .hook = ip_vs_reply6, .pf = NFPROTO_IPV6, .hooknum = NF_INET_FORWARD, .priority = 100, },#endif};
由于是浅析,故这里就不会分析IPV6的场景,主要看ipv4的场景。
.hook涉及到的函数有:
- ip_vs_reply4
- ip_vs_remote_request4
- ip_vs_local_reply4
- ip_vs_local_request4
- ip_vs_forward_icmp
- ip_vs_reply4
netfilter钩子函数最后返回值主要有这几种:
.pf是IP类型,这里只讨论IPV4的情况
.hooknum则是涉及到netfilter的五处钩子点,简单可以理解为,netfilter在内核协议栈中五处地方有函数指针,如果注册了钩子函数,则会在对应点调用指定的钩子函数,处理报文。netfilter的五处分别为:NF_IP_PRE_ROUTING,在完整性校验之后,选路确定之前;NF_IP_LOCAL_IN,在选路确定之后,且数据包的目的是本地主机;NF_IP_FORWARD,目的地是其它主机地数据包;NF_IP_LOCAL_OUT,来自本机进程的数据包在其离开本地主机的过程中;NF_IP_POST_ROUTING,在数据包离开本地主机“上线”之前。
可以看到在ipvs中,主要用到了NF_IP_LOCAL_IN、NF_IP_LOCAL_OUT、NF_IP_FORWARD。
.priority则是表示优先级,因为可能会挂多个钩子函数,所以设置优先级,会先调用优先级高的,再调用优先级低的进行处理。
下一步
可以看到ip_vs_reply4、ip_vs_local_reply4都是调用了ip_vs_out
ip_vs_remote_request4、ip_vs_local_request4都是调用了ip_vs_in
下面将会简要分析ip_vs_out和ip_vs_in两个函数的处理流程
- IPVS负载均衡(六)浅析ip_vs_core.c
- ipvs负载均衡(三)ipvs三种工作方式
- ipvs负载均衡(一)基本概念
- ipvs负载均衡(二)lvs集群介绍
- ipvs负载均衡(四)推荐个原理网站
- ipvs负载均衡(五)代码结构简易分析
- ipvs负载均衡(四)ipvs三种工作方式之tun模式
- LVS IPVS负载均衡机制详解
- 负载均衡实战之一:lvs 核心ipvs
- ipvs负载均衡模块的内核实现
- FreeBSD6.1 +CARP+IPVS双机热备份负载均衡技术
- IPVS-DR+heartbeat+ldirectord实现高可用负载均衡集
- IPVS-DR+heartbeat+ldirectord实现高可用负载均衡集
- 使用IPVS实现Kubernetes入口流量负载均衡
- 均衡负载--浅析
- JBOSS系列(六)--负载均衡
- 六种负载均衡算法
- 六.负载均衡的算法
- Oozie自学(二)-运行job、function、workflow、coordinnate
- taidou服务器创建流程
- Ecplise集成PMD
- A*寻路
- android开发中相见恨晚的冷知识【简单说】
- IPVS负载均衡(六)浅析ip_vs_core.c
- 学习C++ -> 类(Classes)的定义与实现
- 网络编程_多线程实现聊天室程序
- 方立勋_30天掌握JavaWeb_MySQL和表约束
- java不用时间格式打印日历
- Android杂谈:如何通过看google工程师的提交记录获取第一手Android资料
- 1602液晶显示温湿度
- 传输层TCP和UDP编程模型
- 泛型编程