以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相关处理方法. 主要有:

  1. /* After packet filtering, forward packet through VS/DR, VS/TUN,
  2. or VS/NAT(change destination), so that filtering rules can be
  3. applied to IPVS. */
  4. static struct nf_hook_ops ip_vs_in_ops = {
  5. .hook = ip_vs_in,
  6. .owner = THIS_MODULE,
  7. .pf = PF_INET,
  8. .hooknum = NF_IP_LOCAL_IN,
  9. .priority = 100,
  10. };
  11.  
  12. /* After packet filtering, change source only for VS/NAT */
  13. static struct nf_hook_ops ip_vs_out_ops = {
  14. .hook = ip_vs_out,
  15. .owner = THIS_MODULE,
  16. .pf = PF_INET,
  17. .hooknum = NF_IP_FORWARD,
  18. .priority = 100,
  19. };
  20.  
  21. /* After packet filtering (but before ip_vs_out_icmp), catch icmp
  22. destined for 0.0.0.0/0, which is for incoming IPVS connections */
  23. static struct nf_hook_ops ip_vs_forward_icmp_ops = {
  24. .hook = ip_vs_forward_icmp,
  25. .owner = THIS_MODULE,
  26. .pf = PF_INET,
  27. .hooknum = NF_IP_FORWARD,
  28. .priority = 99,
  29. };
  30.  
  31. /* Before the netfilter connection tracking, exit from POST_ROUTING */
  32. static struct nf_hook_ops ip_vs_post_routing_ops = {
  33. .hook = ip_vs_post_routing,
  34. .owner = THIS_MODULE,
  35. .pf = PF_INET,
  36. .hooknum = NF_IP_POST_ROUTING,
  37. .priority = NF_IP_PRI_NAT_SRC-1,
  38. };

下面主要分析下四个钩子是如何工作的.

首先报文从out->in方向发到本地的报文进入ip_vs_in处理/*

  1. * Check if it's for virtual services, look it up,
  2. * and send it on its way...
  3. */
  4. static unsigned int
  5. ip_vs_in(unsigned int hooknum, struct sk_buff **pskb,
  6. const struct net_device *in, const struct net_device *out,
  7. int (*okfn)(struct sk_buff *))
  8. {
  9. struct sk_buff *skb = *pskb;
  10. struct iphdr *iph;
  11. struct ip_vs_protocol *pp;
  12. struct ip_vs_conn *cp;
  13. int ret, restart;
  14. int ihl;
  15. /*
  16. * Big tappo: only PACKET_HOST (neither loopback nor mcasts)
  17. * ... don't know why 1st test DOES NOT include 2nd (?)
  18. */
  19. PACKET_HOST代表什么?
  20. PACKET_HOST代表本地的报文,即mac地址为本机网卡mac地址
  21. if (unlikely(skb->pkt_type != PACKET_HOST
  22. || skb->dev == &loopback_dev || skb->sk)) {
  23. IP_VS_DBG(12, "packet type=%d proto=%d daddr=%d.%d.%d.%d ignored\n",
  24. skb->pkt_type,
  25. skb->nh.iph->protocol,
  26. NIPQUAD(skb->nh.iph->daddr));
  27. return NF_ACCEPT;
  28. }
  29. iph = skb->nh.iph;
  30. if (unlikely(iph->protocol == IPPROTO_ICMP)) {
  31. int related, verdict = ip_vs_in_icmp(pskb, &related, hooknum);
  32. if (related)
  33. return verdict;
  34. skb = *pskb;
  35. iph = skb->nh.iph;
  36. }
  37. //此处为ip_vs_protol_init时注册的协议
  38. /* Protocol supported? */
  39. pp = ip_vs_proto_get(iph->protocol);
  40. if (unlikely(!pp))
  41. return NF_ACCEPT;
  42. ihl = iph->ihl << 2;
  43. /*
  44. * Check if the packet belongs to an existing connection entry
  45. */
  46. // 根据不同协议的定义,查找此连接是否已经存在,或没有查找到则说明之前此连接并未建立过,
    // 需要为这个连接通过conn_schedule选择rserver.并将此连接信息存入ip_vs_conn_tab数组中.
  47. cp = pp->conn_in_get(skb, pp, iph, ihl, 0);
  48. if (unlikely(!cp)) {
  49. int v;
  50. if (!pp->conn_schedule(skb, pp, &v, &cp))
  51. return v;
  52. }
  53. if (unlikely(!cp)) {
  54. /* sorry, all this trouble for a no-hit :) */
  55. IP_VS_DBG_PKT(12, pp, skb, 0,
  56. "packet continues traversal as normal");
  57. return NF_ACCEPT;
  58. }
  59. IP_VS_DBG_PKT(11, pp, skb, 0, "Incoming packet");
  60.   如果rserver状态异常则将连接删除(expire?),并将此报文丢弃.
  61. /* Check the server status */
  62. if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
  63. /* the destination server is not available */
  64. if (sysctl_ip_vs_expire_nodest_conn) {
  65. /* try to expire the connection immediately */
  66. ip_vs_conn_expire_now(cp);
  67. }
  68. /* don't restart its timer, and silently
  69. drop the packet. */
  70. __ip_vs_conn_put(cp);
  71. return NF_DROP;
  72. }
  73. ip_vs_in_stats(cp, skb);
  74. restart = ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pp);
  75. //关键:根据不同的lvs模式(DR NAT等)将报文做不同的发送处理(ip_vs_conn_new->ip_vs_bind_xmit)
  76.   //例:DR模式调用ip_vs_dr_xmit,其中查询路由完成之后调用IP_VS_XMIT,走NF_IP_LOCAL_OUT进入netfilter框架处理.
  77. if (cp->packet_xmit)
  78. ret = cp->packet_xmit(skb, cp, pp);
  79. /* do not touch skb anymore */
  80. else {
  81. IP_VS_DBG_RL("warning: packet_xmit is null");
  82. ret = NF_ACCEPT;
  83. }
  84. /* increase its packet counter and check if it is needed
  85. to be synchronized */
  86. atomic_inc(&cp->in_pkts);
  87. if ((ip_vs_sync_state & IP_VS_STATE_MASTER) &&
  88. (cp->protocol != IPPROTO_TCP ||
  89. cp->state == IP_VS_TCP_S_ESTABLISHED) &&
  90. (atomic_read(&cp->in_pkts) % sysctl_ip_vs_sync_threshold[1]
  91. == sysctl_ip_vs_sync_threshold[0]))
  92. ip_vs_sync_conn(cp);
  93. ip_vs_conn_put(cp);
  94. return ret;
  95. }

 to be contined.

引用:

http://blog.csdn.net/majieyue/article/details/8574580

lvs源代码分析的更多相关文章

  1. LVS 源代码分析

    http://blog.chinaunix.net/uid/11207493.html http://zh.linuxvirtualserver.org/blog/3309

  2. android-plugmgr源代码分析

    android-plugmgr是一个Android插件加载框架,它最大的特点就是对插件不需要进行任何约束.关于这个类库的介绍见作者博客,市面上也有一些插件加载框架,但是感觉没有这个好.在这篇文章中,我 ...

  3. Twitter Storm源代码分析之ZooKeeper中的目录结构

    徐明明博客:Twitter Storm源代码分析之ZooKeeper中的目录结构 我们知道Twitter Storm的所有的状态信息都是保存在Zookeeper里面,nimbus通过在zookeepe ...

  4. 转:SDL2源代码分析

    1:初始化(SDL_Init()) SDL简介 有关SDL的简介在<最简单的视音频播放示例7:SDL2播放RGB/YUV>以及<最简单的视音频播放示例9:SDL2播放PCM>中 ...

  5. 转:RTMPDump源代码分析

    0: 主要函数调用分析 rtmpdump 是一个用来处理 RTMP 流媒体的开源工具包,支持 rtmp://, rtmpt://, rtmpe://, rtmpte://, and rtmps://. ...

  6. 转:ffdshow 源代码分析

    ffdshow神奇的功能:视频播放时显示运动矢量和QP FFDShow可以称得上是全能的解码.编码器.最初FFDShow只是mpeg视频解码器,不过现在他能做到的远不止于此.它能够解码的视频格式已经远 ...

  7. UiAutomator源代码分析之UiAutomatorBridge框架

    上一篇文章<UIAutomator源代码分析之启动和执行>我们描写叙述了uitautomator从命令行执行到载入測试用例执行測试的整个流程.过程中我们也描写叙述了UiAutomatorB ...

  8. MyBatis架构设计及源代码分析系列(一):MyBatis架构

    如果不太熟悉MyBatis使用的请先参见MyBatis官方文档,这对理解其架构设计和源码分析有很大好处. 一.概述 MyBatis并不是一个完整的ORM框架,其官方首页是这么介绍自己 The MyBa ...

  9. hostapd源代码分析(三):管理帧的收发和处理

    hostapd源代码分析(三):管理帧的收发和处理 原文链接:http://blog.csdn.net/qq_21949217/article/details/46004379 这篇文章我来讲解一下h ...

随机推荐

  1. jQuery UI Datepicker

    http://www.runoob.com/try/try.php?filename=jqueryui-example-datepicker-dropdown-month-year <!doct ...

  2. 转一篇介绍Web session概念的文章

    说的非常好,如果你对web中的session概念不太清楚的话,一定要去看看,可能需要FQ才能阅读:http://fred-zone.blogspot.com/2014/01/web-session.h ...

  3. Delete,Update与LEFT Join

    UPDATE:UPDATE A SET ApproverID=NULL FROM [SH_MaterialApplyBuyBill] A LEFT JOIN [SH_MaterialApplyBuyB ...

  4. ABAP 上传文件到内表

    http://www.cnblogs.com/jiangzhengjun/p/4265642.html http://www.xuebuyuan.com/1233478.html

  5. Java控件(日常笔记)

    Java的一些控件 text:文本区域 readonly属性:是否只读.password:密码区域,输入的文本以'*'展示checkbox:复选框 checked属性:是否选中:radio:单选框: ...

  6. request getParameter getAttribute

    在浏览器地址输入,表示传入一个参数test,值为123 http://localhost:8888/Test/index.jsp?test=123 在index.jsp中尝试使用EL表达式取出,代码如 ...

  7. hdu 1502 Regular Words

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=1502 思路:给定一个n,分别由n个a,b,c组成的字符串的所有前缀中a的个数大于等于b的个数大于等于c的个 ...

  8. HTTP TCP UDP Socket 关系的几个经典图

      从上图可以看到,TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层. 在网络层有IP协议.ICMP协议.ARP协议.RARP协议和BOOTP协议. 在传输层中有TCP协议与UDP协议. ...

  9. intellij idea 插件 ideaVim 用法

    intellij idea 插件 ideaVim - Genji_ - 博客园http://www.cnblogs.com/nova-/p/3535636.html IdeaVim插件使用技巧 - - ...

  10. 工欲善其事-Eclipse设置

    1.注释设置 [重要可以保存使用] 在菜单栏Window--->Preferences--->Java--->Code Style--->Code Templates然后展示C ...