zoukankan      html  css  js  c++  java
  • ipvs学习笔记(二)

    3.6ipvs数据包发送

    IPVS连接中的数据包的发送方法是由ip_vs_bind_xmit()(net\netfilter\ipvs\ip_vs_conn.c)函数定义的,具体的发送数据包处理函数定义net\netfilter\ipvs\Ip_vs_xmit.c文件中

    int

    ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,

           struct ip_vs_protocol *pp)

    NAT发送只发送请求方向的数据,因此是进行目的NAT

    int

    ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,

      struct ip_vs_protocol *pp)

    TUNNEL发送是把原来的IP部分再加在一个IPIP协议(4)头后发出去,新头的目的IP是真实目的服务器,源IP是真实客户端IP,该包是可以路由的,服务器的回应包将直接路由回去而不经过IPVS.

    int

    ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,

          struct ip_vs_protocol *pp)

    DR发送是将原来的skb包中的目的MAC地址修改为目的服务器的MAC地址后直接发出,因此是不能路由的,IPVS均衡设备和目的服务器物理上必须在同一个二层子网。在DR模式下,IPVS和服务器都配置了相同的对外服务的VIP,服务器也配了自己的真实IP,不过服务器上配VIP的网卡属性中的NOARP信息是打开的,就是在该网卡上不响应ARP信息,但可以接收到达该VIP的数据包,这样外面请求包先是到IPVS均衡器,因为IPVS的VIP是响应ARP的,然后根据调度找一台服务器,用服务器的真实IP来确定路由,然后直接把包发出来,这时包中所有数据都没修改,因为目的服务器上VIP地址符合包中的目的地址,因此是可以接收该包的。

    int

    ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,

      struct ip_vs_protocol *pp)

    旁路模式,实际数据包不是给IPVS均衡器自己的,由IPVS进行转发

    int

    ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,

    struct ip_vs_protocol *pp, int offset, unsigned int hooknum)

    发送各种ICMP错误信息包

    3.7ipvs的应用管理

    IPVS的应用是针对象FTP等的多连接协议处理的,由于多连接协议的特殊性,任何以连接为基础进行处理的模块如IPVS,netfilter等都必须对这些协议特别处理,不过IPVS相对没有netfilter那么完善,目前也仅仅支持FTP协议,而netfilter已经可以支持FTP、TFTP、IRC、AMANDA、MMS、SIP、H.323等多种多连接协议。

    IPVS应用也是模块化的,不过其实现有点特别,对于每一个应用协议,会定义一个静态的struct ip_vs_app结构作为模板,以后登记该协议时,对应的应用指针并不是直接指向这个静态结构,而是新分配一个struct ip_vs_app结构,结构中的struct ip_vs_app指针指向这个静态结构,然后把新分配的这个结构分别挂接到静态struct ip_vs_app结构的具体实现链表和IP协议的应用HASH链表中进行使用,这种实现方法和netfilter完全不同。

    IPVS应用一些共享的处理函数在net\netfilter\ipvs\ip_vs_app.c中定义,其他各协议相关处理分别由各自文件处理,如net\netfilter\ipvs\ip_vs_ftp.c.

    3.8ipvs的主备同步

    IPVS支持对连接的同步,两台IPVS设备可分别以MASTER或BACKUP运行,MASTER进程可将连接信息备份到BACKUP设备上,这样主设备死机时从设备可以无缝切换。

    可以在IPVS设备上同时启动MASTER和BACKUP进程,使设备之间互为备份,实现IPVS设备的均衡。

    IPVS同步实现在net\netfilter\ipvs\ip_vs_sync.c中

    3.9ipvs预估器

    IPVS预估器用的估算在一个短暂时间间隔内的连接率,可在用户空间开一个daemon定时读取预估器的值以实现较长时间的预估。

    预估算法为:

    取最后8秒钟内,每两秒取一个采样点进行平滑处理:

        avgrate = avgrate*(1-W) + rate*W

        其中 W = 2^(-2) = 0.25,速率单位是KBytes/s

    预估代码在net\netfilter\ipvs\ip_vs_est.c中实现。

    3.10ipvs的/proc参数

    ipvs在/proc目录下建立了以下文件:

    /proc/net:

     /proc/net/ip_vs:IPVS的规则表

     /proc/net/ip_vs_app:IPVS应用协议

     /proc/net/ip_vs_conn:IPVS当前连接

     /proc/net/ip_vs_stats:IPVS状态统计信息

    /proc/sys/net/ipv4/vs:

     /proc/sys/net/ipv4/vs/am_droprate:丢包率(缺省10)

     /proc/sys/net/ipv4/vs/amemthresh:可用内存阈值(缺省1024)

     /proc/sys/net/ipv4/vs/cache_bypass:是否建立旁路cache项

     /proc/sys/net/ipv4/vs/debug_level:调试级别

     /proc/sys/net/ipv4/vs/drop_entry:确定删除连接处理级别

     /proc/sys/net/ipv4/vs/drop_packet:丢包级别

     /proc/sys/net/ipv4/vs/expire_nodest_conn:是否删除没有目的服务器的连接

     /proc/sys/net/ipv4/vs/lblc_expiration:lblc算法的到期时间(缺省1天)

     /proc/sys/net/ipv4/vs/lblcr_expiration:lblcr算法的到期时间(缺省1天)

     /proc/sys/net/ipv4/vs/nat_icmp_send:NAT模式下连接异常时发送ICMP包

     /proc/sys/net/ipv4/vs/secure_tcp:更安全的TCP状态转换

     /proc/sys/net/ipv4/vs/sync_threshold:连接同步时的包数阈值数值

     /proc/sys/net/ipv4/vs/timeout_close:TCP sCL状态超时

     /proc/sys/net/ipv4/vs/timeout_closewait:TCP sCW状态超时

     /proc/sys/net/ipv4/vs/timeout_established:TCP sES状态超时

     /proc/sys/net/ipv4/vs/timeout_finwait:TCP sFW状态超时

     /proc/sys/net/ipv4/vs/timeout_icmp:ICMP超时

     /proc/sys/net/ipv4/vs/timeout_lastack:TCP sLA状态超时

     /proc/sys/net/ipv4/vs/timeout_listen:TCP sLI状态超时

     /proc/sys/net/ipv4/vs/timeout_synack:TCP sSA状态超时

     /proc/sys/net/ipv4/vs/timeout_synrecv:TCP sSR状态超时

     /proc/sys/net/ipv4/vs/timeout_synsent:TCP sSS状态超时

     /proc/sys/net/ipv4/vs/timeout_timewait:TCP sTW状态超时

     /proc/sys/net/ipv4/vs/timeout_udp:UDP超时

    3.11ipvs控制

    ipvs控制包括定义IPVS提供的虚拟服务参数和实际的目的服务器等各种参数。

    ipvs的控制信息是通过setsockopt系统调用传递到内核的,ipvs在用户层的管理工具是ipvsadm。

    关于ipvs控制代码在net\netfilter\ipvs\ip_vs_ctl.c中。

    3.11.1注册sockopt

    static struct nf_sockopt_ops ip_vs_sockopts = {

    .pf                = PF_INET,

    .set_optmin        = IP_VS_BASE_CTL,

    .set_optmax        = IP_VS_SO_SET_MAX+1,

    .set                = do_ip_vs_set_ctl,

    .get_optmin        = IP_VS_BASE_CTL,

    .get_optmax        = IP_VS_SO_GET_MAX+1,

    .get                = do_ip_vs_get_ctl,

    .owner                = THIS_MODULE,

    };

    借用netfilter的struct nf_sockopt_ops结构来添加

    int __init ip_vs_control_init(void)函数中调用

    ret = nf_register_sockopt(&ip_vs_sockopts);来注册sockopt

    static int

    do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)

    写控制

    static int

    do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)

    读控制

    3.11.2、服务控制

    static int

    ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u,

      struct ip_vs_service **svc_p)

    添加服务

    static int

    ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)

    修改服务和绑定一个新的调度器

    static int ip_vs_del_service(struct ip_vs_service *svc)

    删除服务

    static int ip_vs_flush(struct net *net)

    删除所有服务

    static int ip_vs_zero_service(struct ip_vs_service *svc)

    清除服务计数器

    3.11.3、真实服务器管理

    static int

    ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)

    添加一个真实服务器到一个已存在的虚拟服务

    static int

    ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,

           struct ip_vs_dest **dest_p)

    在一个虚拟服务中创建一个真实服务器结构

    static int

    ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)

    修改真实服务器

    static int

    ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)

    在一个虚拟服务中删除真实服务器

    static void __ip_vs_del_dest(struct net *net, struct ip_vs_dest *dest)

    删除一个真实服务器(必须已与虚拟服务解绑)

    static void __ip_vs_unlink_dest(struct ip_vs_service *svc,

    struct ip_vs_dest *dest,

    int svcupd)

    在一个虚拟服务中解绑真实服务器

    3.11.4防御级别调整

    static void defense_work_handler(struct work_struct *work)

    定时处理函数

    static void update_defense_level(struct netns_ipvs *ipvs)

    更新IPVS的防御级别,需要用到/proc下定义的一些控制参数

    4、学习总结

    对于对linux内核不了解的人来说,最开始看ipvsipvsadm代码时会一头雾水,但对内核编程初步了解与看yfydz老大的实现分析系列文章后使我茅塞顿开。ipvs的结构体定义与功能函数实现一目了然,某些关键细节还没有看的很透彻,不过已可以定位关键点了。ipvsadmipvs之间的控制通信通过setsockopt实现,对照看一些结构体的填充与用户层和内核之间的数据传递,可对控制工作流程有直观的了解。最后挖掘的地方就是数据包修改功能与调度策略的算法实现,这样使我对ipvs的代码实现熟悉起来。希望我整理的函数列表会对大家有帮助,一直看yfydz的大篇注释有点晕,需要了解的地方再跟进查看吧,感谢ipvs作者与yfydz的技术分享。

  • 相关阅读:
    时间过的好快啊
    IBM的 SOA架构设计还是写的很好的
    昨天尝试了Layout,也谈Silverlight的布局
    这几天忙着选车了!
    痛苦的事情是将自己的想法表达出来
    花了一天的工夫才写了一篇PPT
    昨天抄写了gameEnvironment的行为模式
    XMLHTTP对像异步请求四步曲
    第一篇: 第一个简单的vs 2008 ASP.NET Ajax 范例
    什么是 Silverlight?
  • 原文地址:https://www.cnblogs.com/qq78292959/p/2589765.html
Copyright © 2011-2022 走看看