lvs源代码分析
以linux-2.6.21为例.
数据结构介绍:
ip_vs_conn
对于某个连接记录其N元组, (client, vserver, rserver) & (address, port)
Q: ip_vs_conn?
A: 在选择rserver的时候,通过scheduler函数来创建rserver并,创建对应的ip_vs_conn,并保存在ip_vs_conn_tab数组中.详见函数ip_vs_schedule ipv4/ipvs/ip_vs_core.c
ip_vs_in->conn_schedule->tcp_conn_schedule->ip_vs_schedule->ip_vs_conn_new
Q: 此连接何时过期?
1. 在检查到rserver状态不为IP_VS_DEST_F_AVAILABLE,则调用ip_vs_conn_expire_now
ip_vs_service
代表了一个virtual server,由链表ip_vs_svc_table统一维护,即所有的vritual server都会在保存在ip_vs_svc_table6.
Q: 何时建立?
A: 在通过用户态命令创建virtual server的时候会创建,详见ip_vs_add_service,相关文件net/ipv4/ipvs/ip_vs_ctl.c
ip_vs_core.c
定义了ip_vs_init函数作为模块初始化的方法
此初始化方法主要做了如下几件事情:
1. ip_vs_control_init 使用nf_register_sockopt注册内核态数据ip_vs_sockopts结构,用来与用户态ipvsadm命令交互
注:和netlink一样,sockopt是内核态与用户态通信的一种方式,详见http://blog.csdn.net/jk110333/article/details/8642261
相关文件:net/ipv4/ipvs/ip_vs_ctl.c
2. ip_vs_protocol_init
此功能主要注册ip_vs_protocol_tcp, ip_vs_protocol_udp, ip_vs_protocol_ah, ip_vs_protocol_esp。注册这些协议的目的是为了使用ip_vs_protocol结构定义,在对支持的协议做lvs相关处理的时候(比如snat,dnat等)时应该调用哪种方法。相关记录在ip_vs_proto_table数组中.
相关文件:include/net/ip_vs.h、net/ipv4/ipvs/ip_vs_proto.c
3. ip_vs_conn_init
分配连接hash表并初始化list_head
相关文件:net/ipv4/ipvs/ip_vs_conn.c
4. 注册hook钩子,以使用netfiler框架调用lvs相关处理方法. 主要有:
/* After packet filtering, forward packet through VS/DR, VS/TUN,
or VS/NAT(change destination), so that filtering rules can be
applied to IPVS. */
static struct nf_hook_ops ip_vs_in_ops = {
.hook = ip_vs_in,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_LOCAL_IN,
.priority = 100,
}; /* After packet filtering, change source only for VS/NAT */
static struct nf_hook_ops ip_vs_out_ops = {
.hook = ip_vs_out,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_FORWARD,
.priority = 100,
}; /* After packet filtering (but before ip_vs_out_icmp), catch icmp
destined for 0.0.0.0/0, which is for incoming IPVS connections */
static struct nf_hook_ops ip_vs_forward_icmp_ops = {
.hook = ip_vs_forward_icmp,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_FORWARD,
.priority = 99,
}; /* Before the netfilter connection tracking, exit from POST_ROUTING */
static struct nf_hook_ops ip_vs_post_routing_ops = {
.hook = ip_vs_post_routing,
.owner = THIS_MODULE,
.pf = PF_INET,
.hooknum = NF_IP_POST_ROUTING,
.priority = NF_IP_PRI_NAT_SRC-1,
};
下面主要分析下四个钩子是如何工作的.
首先报文从out->in方向发到本地的报文进入ip_vs_in处理/*
* Check if it's for virtual services, look it up,
* and send it on its way...
*/
static unsigned int
ip_vs_in(unsigned int hooknum, struct sk_buff **pskb,
const struct net_device *in, const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
struct sk_buff *skb = *pskb;
struct iphdr *iph;
struct ip_vs_protocol *pp;
struct ip_vs_conn *cp;
int ret, restart;
int ihl; /*
* Big tappo: only PACKET_HOST (neither loopback nor mcasts)
* ... don't know why 1st test DOES NOT include 2nd (?)
*/
PACKET_HOST代表什么?
PACKET_HOST代表本地的报文,即mac地址为本机网卡mac地址
if (unlikely(skb->pkt_type != PACKET_HOST
|| skb->dev == &loopback_dev || skb->sk)) {
IP_VS_DBG(12, "packet type=%d proto=%d daddr=%d.%d.%d.%d ignored\n",
skb->pkt_type,
skb->nh.iph->protocol,
NIPQUAD(skb->nh.iph->daddr));
return NF_ACCEPT;
} iph = skb->nh.iph;
if (unlikely(iph->protocol == IPPROTO_ICMP)) {
int related, verdict = ip_vs_in_icmp(pskb, &related, hooknum); if (related)
return verdict;
skb = *pskb;
iph = skb->nh.iph;
}
//此处为ip_vs_protol_init时注册的协议
/* Protocol supported? */
pp = ip_vs_proto_get(iph->protocol);
if (unlikely(!pp))
return NF_ACCEPT; ihl = iph->ihl << 2; /*
* Check if the packet belongs to an existing connection entry
*/
// 根据不同协议的定义,查找此连接是否已经存在,或没有查找到则说明之前此连接并未建立过,
// 需要为这个连接通过conn_schedule选择rserver.并将此连接信息存入ip_vs_conn_tab数组中.
cp = pp->conn_in_get(skb, pp, iph, ihl, 0);
if (unlikely(!cp)) {
int v;
if (!pp->conn_schedule(skb, pp, &v, &cp))
return v;
} if (unlikely(!cp)) {
/* sorry, all this trouble for a no-hit :) */
IP_VS_DBG_PKT(12, pp, skb, 0,
"packet continues traversal as normal");
return NF_ACCEPT;
} IP_VS_DBG_PKT(11, pp, skb, 0, "Incoming packet"); 如果rserver状态异常则将连接删除(expire?),并将此报文丢弃.
/* Check the server status */
if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
/* the destination server is not available */ if (sysctl_ip_vs_expire_nodest_conn) {
/* try to expire the connection immediately */
ip_vs_conn_expire_now(cp);
}
/* don't restart its timer, and silently
drop the packet. */
__ip_vs_conn_put(cp);
return NF_DROP;
} ip_vs_in_stats(cp, skb);
restart = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pp);
//关键:根据不同的lvs模式(DR NAT等)将报文做不同的发送处理(ip_vs_conn_new->ip_vs_bind_xmit)
//例:DR模式调用ip_vs_dr_xmit,其中查询路由完成之后调用IP_VS_XMIT,走NF_IP_LOCAL_OUT进入netfilter框架处理.
if (cp->packet_xmit)
ret = cp->packet_xmit(skb, cp, pp);
/* do not touch skb anymore */
else {
IP_VS_DBG_RL("warning: packet_xmit is null");
ret = NF_ACCEPT;
} /* increase its packet counter and check if it is needed
to be synchronized */
atomic_inc(&cp->in_pkts);
if ((ip_vs_sync_state & IP_VS_STATE_MASTER) &&
(cp->protocol != IPPROTO_TCP ||
cp->state == IP_VS_TCP_S_ESTABLISHED) &&
(atomic_read(&cp->in_pkts) % sysctl_ip_vs_sync_threshold[1]
== sysctl_ip_vs_sync_threshold[0]))
ip_vs_sync_conn(cp); ip_vs_conn_put(cp);
return ret;
}
to be contined.
引用:
http://blog.csdn.net/majieyue/article/details/8574580
lvs源代码分析的更多相关文章
- LVS 源代码分析
http://blog.chinaunix.net/uid/11207493.html http://zh.linuxvirtualserver.org/blog/3309
- android-plugmgr源代码分析
android-plugmgr是一个Android插件加载框架,它最大的特点就是对插件不需要进行任何约束.关于这个类库的介绍见作者博客,市面上也有一些插件加载框架,但是感觉没有这个好.在这篇文章中,我 ...
- Twitter Storm源代码分析之ZooKeeper中的目录结构
徐明明博客:Twitter Storm源代码分析之ZooKeeper中的目录结构 我们知道Twitter Storm的所有的状态信息都是保存在Zookeeper里面,nimbus通过在zookeepe ...
- 转:SDL2源代码分析
1:初始化(SDL_Init()) SDL简介 有关SDL的简介在<最简单的视音频播放示例7:SDL2播放RGB/YUV>以及<最简单的视音频播放示例9:SDL2播放PCM>中 ...
- 转:RTMPDump源代码分析
0: 主要函数调用分析 rtmpdump 是一个用来处理 RTMP 流媒体的开源工具包,支持 rtmp://, rtmpt://, rtmpe://, rtmpte://, and rtmps://. ...
- 转:ffdshow 源代码分析
ffdshow神奇的功能:视频播放时显示运动矢量和QP FFDShow可以称得上是全能的解码.编码器.最初FFDShow只是mpeg视频解码器,不过现在他能做到的远不止于此.它能够解码的视频格式已经远 ...
- UiAutomator源代码分析之UiAutomatorBridge框架
上一篇文章<UIAutomator源代码分析之启动和执行>我们描写叙述了uitautomator从命令行执行到载入測试用例执行測试的整个流程.过程中我们也描写叙述了UiAutomatorB ...
- MyBatis架构设计及源代码分析系列(一):MyBatis架构
如果不太熟悉MyBatis使用的请先参见MyBatis官方文档,这对理解其架构设计和源码分析有很大好处. 一.概述 MyBatis并不是一个完整的ORM框架,其官方首页是这么介绍自己 The MyBa ...
- hostapd源代码分析(三):管理帧的收发和处理
hostapd源代码分析(三):管理帧的收发和处理 原文链接:http://blog.csdn.net/qq_21949217/article/details/46004379 这篇文章我来讲解一下h ...
随机推荐
- ffmpeg-20160901-bin.7z
ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 5 屏幕横向放大 20 像素 6 屏幕横向缩小 20 像素 S 下一帧 [ -2秒 ] +2 ...
- 15.django之Django-Rest-Framework
1.首先安装Django-Rest-Framework pip3 install djangorestframework pip3 install markdown Markdown为可视化 API ...
- SQL语句汇总
1.查询出来数据保留小数点2位,并且0.01时候,不会展示为.01. select to_char(0.1,'fm9999999990.00') from dual; 2.wm_concat ...
- Logistic回归 python实现
Logistic回归 算法优缺点: 1.计算代价不高,易于理解和实现2.容易欠拟合,分类精度可能不高3.适用数据类型:数值型和标称型 算法思想: 其实就我的理解来说,logistic回归实际上就是加了 ...
- Javascript函数重载,存在呢—还是存在呢?
1.What's is 函数重载? );//Here is int 10 print("ten");//Here is string ten } 可以发现在C++中会根据参数的类型 ...
- Android 框架练成 教你打造高效的图片加载框架(转)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/41874561,本文出自:[张鸿洋的博客] 1.概述 优秀的图片加载框架不要太多, ...
- Deep Learning模型之:CNN卷积神经网络(一)深度解析CNN
http://m.blog.csdn.net/blog/wu010555688/24487301 本文整理了网上几位大牛的博客,详细地讲解了CNN的基础结构与核心思想,欢迎交流. [1]Deep le ...
- HDU 2045 不容易系列之(3)―― LELE的RPG难题(递推)
题意:有排成一行的n个方格,用红(Red).粉(Pink).绿(Green)三色涂每个格子,每格涂一色,要求任何相邻的方格不能同色,且首尾两格也不同色.求全部的满足要求的涂法. 题解:本来当n=1时, ...
- java-集合4
浏览以下内容前,请点击并阅读 声明 对象排序 一个List对象中如果元素类型为String,则其按字母表顺序排序,而如果元素类型为Date,则按照年代排序,那如何判断元素的排序呢?String和Dat ...
- [软件推荐]VMware Workstation 12.1.1多国语言(含简体中文)+激活方法
虚拟机VMware功能强大,使用方便,可以在同一台电脑上安装多个系统(Windows.Linux.OS).虚拟机上的所有操作都不会影响到“实体机”,因此在虚拟机中可以进行很多测试操作,如果某些软件使用 ...