当前位置:  技术问答>linux和unix

[百度分享]Bonding 模块代码及主要工作模式分析(1)

    来源: 互联网  发布时间:2016-10-21

    本文导语:     1.  目的    本文档结合相关内核代码和对Linux 2.6.9内核中Bonding模块的三种主要工作模式的工作原理和流程。在配置Bond模块时,除了资料[2],本文档也有一定的参考价值。    2. 内容 本文档包含下列内容:...

   1.  目的

   本文档结合相关内核代码和对Linux 2.6.9内核中Bonding模块的三种主要工作模式的工作原理和流程。在配置Bond模块时,除了资料[2],本文档也有一定的参考价值。

   2. 内容

本文档包含下列内容:

    * Bonding模块工作流程综述。(第3节)
    * Bonding链路状态监控机制(mii模式、arp模式)描述。(第4节)
    * Bonding模块三种主要工作模式:balance-rr、active- backup和broadcast相关代码分析。(第5节)
    * Bonding模块关键数据结构和函数的代码分析。(第5节)

   如果想了解bonding模块的原理和工作流程,请阅读3、4节,如果想进一步分析bonding模块的代码,请阅读5节。

   3. Bonding模块工作流程综述

   Bonding模块本质上是一个虚拟的网卡驱动(network device driver),只不过并没有真实的物理网卡与之对应,而是由这个虚拟网卡去“管辖”一系列的真实的物理网卡,所以它的代码结构和一般网卡驱动的代码结构非常类似,这是共性;除此之外,它还有自己的一些特性功能,例如特别的链路状态监控机制,绑定/解除绑定等。

         1. 物理网卡的活动状态和链路状态:

   在bonding模块中为每一个被绑定的物理网卡定义了两种活动状态和四种链路状态:注意,这里的链路状态和实际网卡真实的链路状态(是否故障、是否有网线连接)没有直接的关系,虽然bonding模块通过MII或者ARP侦测到实际网卡故障时也会改变自定义的链路状态值(例如从BOND_LINK_UP切换到BOND_LINK_FAIL随后切换到 BOND_LINK_DOWN状态),但是概念上应该把这两类链路状态区分开。在本文档随后的内容中,除非特别指出,“链路状态”都指bonding模块自定义的链路状态。

   活动状态:

    * BOND_STATE_ACTIVE:处于该状态的网卡是潜在的发送数据包的候选者
    * BOND_STATE_BACKUP:处于该状态的网卡在选择发送数据的网卡时被排除

   链路状态:

    * BOND_LINK_UP:  上线状态(处于该状态的网卡是是潜在的发送数据包的候选者)
    * BOND_LINK_DOWN:故障状态
    * BOND_LINK_FAIL:网卡出现故障,向状态BOND_LINK_DOWN 切换中
    * BOND_LINK_BACK:网卡恢复,向状态BOND_LINK_UP切换中

   一个网卡必须活动状态为BOND_STATE_ACTIVE并且链路状态为 BOND_LINK_UP,才有可能作为发送数据包的候选者,注意,这里所说的数据包并不包含ARP请求,在使用ARP链路状态监控时,一个处于BOND_LINK_BACK状态的网卡也可能发送ARP请求。

   bonding模块的所有工作模式可以分为两类:多主型工作模式和主备型工作模式,balance-rr 和broadcast属于多主型工作模式而active-backup属于主备型工作模式。(balance-xor、自适应传输负载均衡模式(balance-tlb)和自适应负载均衡模式(balance-alb)也属于多主型工作模式,IEEE 802.3ad动态链路聚合模式(802.3ad)属于主备型工作模式,在本文档中不加以讨论)

   在多主型工作模式中,如果物理网卡不出现故障,所有的物理网卡都处于 BOND_STATE_ACTIVE和BOND_LINK_UP的状态下,参与数据的收发,此时:如果工作在balance-rr 模式中轮流向各个网卡发送数据,curr_active_slave字段(见5.1.3)指向前次发送数据(不包含ARP请求)的物理网卡,该指针每次发送过数据后都会切换到下一个物理网卡;在broadcast模式中向所有网卡发送数据,curr_active_slave字段除非网卡有故障发生不会切换。

   在主备型工作模式中,如果物理网卡不出现故障,只有一块网卡(活动网卡)处于 BOND_STATE_ACTIVE和BOND_LINK_UP的状态下,负责数据的收发,而其他网卡(后备网卡)处于BOND_STATE_BACKUP 和BOND_LINK_DOWN状态下,此时curr_active_slave字段指向当前的活动网卡。

   如果工作在active-backup模式下,可以指定一个物理网卡作为主网卡(primitive interface),如果主网卡可用,就把主网卡作为当前活动网卡,否则在其他的可用网卡中选取一块网卡作为当前活动网卡,而一旦主网卡从故障中恢复,不管当前活动网卡是否故障都切换到主网卡。在balance-tlb和balance-alb模式中也可以指定主网卡,但是其意义和active-backup模式中并不相同。

         2. 数据收发流程

   如果一个物理网卡被虚拟网卡绑定,则代表该网卡的数据结构struct net_device中下列字段将发生变化:

    * flags字段(unsigned short)将包含IFF_SLAVE标志。
    * master字段(struct net_device *)将指向虚拟网卡。

   在主备型工作模式下,所有的非活动物理网卡的flags字段还将设置IFF_NOARP标志位表示对ARP请求不做出回应。

   而代表虚拟网卡的struct net_device数据结构的flags字段将包含IFF_MASTER标志。

   所有被绑定的物理网卡都将被设置相同的MAC地址和MTU值(和虚拟网卡也相同),这些值将和第一块被绑定的物理网卡保持一致(“第一块网卡”并不是一个强制条件,这是由bonding模块的启动流程造成的,我们也可以手工设置虚拟网卡的MAC地址和MTU值,这个设定同时也将用于所有被绑定的物理网卡)。另外,所有被绑定的物理网卡没有IP地址,所以不参与发送IP数据包的路由选择。

   在下面的三节中,只描述数据发送和接收过程中和bonding相关的一些特殊处理,关于Linux内核的一般数据包收发流程请参考资料[3][4],本文档不再赘述。

               1. 接收数据

   无论在何种模式下,只要物理网卡的实际链路状态正常,任何被绑定的物理网卡都可以接收数据(虽然没有IP地址,但是仍然有MAC地址),即使是处于BOND_STATE_BACKUP和BOND_LINK_DOWN状态时,这是由于BOND_STATE_BACKUP和BOND_LINK_DOWN是bonding模块自己定义的管理物理网卡所用的状态,和内核的TCP/IP栈没有任何关系,bonding模块最多在主备模式下给备用物理网卡设置IFF_NOARP标志,使它对ARP数据包不做出回应,仅此而已。

   收取数据包时,物理网卡驱动的中断处理函数把数据包放入接收队列中,随后软中断NET_RX_SOFTIRQ的处理函数net_rx_action被调用,该函数将调用接收数据包的物理网卡网卡的poll函数。

   无论一个物理网卡是否支持NAPI,函数netif_receive_skb都将在某个阶段被调用。(如果物理网卡不支持NAPI,内核使用函数process_backlog代替真实的poll调用,而process_backlog调用netif_receive_skb)。

   在netif_receive_skb函数中将调用函数skb_bond,该函数本质上作如下操作:

   if(dev->master) skb->dev = dev->master;

   即把数据包skb的物理网卡字段替换为虚拟网卡,使得该数据包看起来像是从虚拟网卡接收的一样,随后的处理和其他数据包没有任何差别,不再赘述。

               2. 发送数据

   发送数据包时,内核根据路由选择某一个虚拟网卡作为发送接口(注意被绑定的物理网卡没有IP地址),最后调用该虚拟网卡的数据包传输接口net_device-> hard_start_xmit,注意此时该数据包中的dev字段指向虚拟网卡。net_device-> hard_start_xmit接口根据不同的工作模式指向不同的传输函数,但是无论是何种工作模式,最后bond_dev_queue_xmit函数都将被调用(以一个选定的物理网卡作为参数调用)。

   bond_dev_queue_xmit函数将作如下操作:

   skb->dev = slave_dev;

   即替换skb的dev字段为选定的物理网卡。

   随后,bond_dev_queue_xmit将调用标准的内核接口dev_queue_xmit把数据包放入选定物理网卡的发送队列中。

               3. ARP请求和回应

   既然被绑定物理网卡没有IP地址,那么如果接收到ARP请求之后,根据何IP地址决定是否产生应答?如果产生应答,在应答中,源IP地址应该是什么?

   答案是:被绑定物理网卡接收到ARP请求后,由于函数arp_rcv在netif_receive_skb之后被调用,而skb->dev经过netif_receive_skb的处理将指向虚拟网卡,所以是否产生应答由该物理网卡所属的虚拟网卡的IP地址决定(当然前提是物理网卡没有设置IFF_NOARP标志),并且最终的ARP回应将包含虚拟网卡的IP地址(细节请参考arp_rcv和arp_process函数)。

   4. 链路状态监控

   链路状态监控有如下两个作用:

    * 根据被绑定物理网卡的实际链路状态(是否故障、网线是否连接)更新bonding模块自定义的物理网卡链路状态和活动状态。
    * 在主备模式下,根据自定义的物理网卡链路状态切换活动状态和当前的活动网卡。

   Bonging模块支持两种模式的链路状态监控:通过MII ioctl调用直接进行或是通过发送ARP请求间接进行。前者通过调用物理网卡驱动程序的MII ioctl接口直接获得物理网卡是否故障的信息,后者通过向预定义的一组IP地址发送ARP请求,并观察被监控物理网卡是否有收到数据包(可能是ARP回答或者是一般数据包)间接进行。

   这两种链路状态监控模式不能并存。参数arp_interval和miimon表示以毫秒为单位的检测间隔,在加载bonding模块时如果指定了非0的arp_interval参数并且miimon参数等于0,则使用ARP链路状态监控;如果指定了非0 miimon参数则使用MII链路状态监控(强制arp_interval = 0从而忽略arp_interval参数)。如果arp_interval和miimon都等于0则使用参数值为100的MII链路状态监控(强制miimon等于100 ms)。

   如果使用ARP链路状态监控,还*必须*指定 arp_ip_target参数,该参数设定ARP监控时发送ARP请求的目标IP列表,各个IP之间使用逗号分隔。

   如果使用MII链路状态监控,还*可以*指定参数updelay和downdelay作为从BOND_LINK_DOWN到BOND_LINK_UP或者从BOND_LINK_UP 到BOND_LINK_DOWN切换的时间间隔,这两个参数默认是0值。(在ARP链路状态监控中这两个参数没有用)

         1. MII链路状态监控

MII链路状态监控可以用下列流程图表示

您的浏览器可能不支持显示此图像。

   初始时,如果虚拟网卡工作在多主型工作模式下,则所有物理网卡的链路状态为BOND_LINK_UP,并且活动状态处于BOND_STATE_ACTIVE,IFF_NOARP标志都没有设置;否则所有物理网卡的链路状态为 BOND_LINK_UP,但是只有当前活动网卡的活动状态处于BOND_STATE_ACTIVE并且没有设置IFF_NOARP 标志,而其余网卡的活动状态为BOND_STATE_BACKUP并且IFF_NOARP标志被设置。

   MII检测机制每miimon毫秒检测一遍所有被绑定物理网卡的状态。

① 在某时刻,如果通过MII调用侦测到某一个物理网卡发生故障,则该物理网卡的链路状态立即被设置为BOND_LINK_FAILED。

② 如果在downdelay毫秒内物理网卡恢复正常,则重新把网卡的链路状态设置为BOND_LINK_UP。

③ 如果在downdelay毫秒内物理网卡始终没有恢复正常,则该物理网卡的链路状态被设置为BOND_LINK_DOWN。如果虚拟网卡工作于主备型工作模式下,则活动状态被设置为BOND_STATE_BACKUP同时设置物理网卡的IFF_NOARP标志,并且如果出故障的是当前活动网卡,则通过一个重选择过程选择新的活动网卡(一般是第一块可用物理网卡)。

④如果一个链路状态为BOND_LINK_DOWN的物理网卡在MII检测过程中恢复正常,则立即把网卡的链路状态设置为BOND_LINK_BACK。

⑤如果在updelay毫秒内物理网卡又发生故障,就把链路状态重新设置为BOND_LINK_DOWN。

⑥如果在updelay毫秒内物理网卡始终保持可用状态,就把链路状态重新设置为BOND_LINK_UP。如果虚拟网卡工作于主备型工作模式下,则同时设置活动状态为BOND_STATE_ACTIVE并且清除物理网卡的IFF_NOARP标志,并且如果是主网卡恢复到BOND_STATE_ACTIVE状态,则会把当前活动网卡切换到主网卡。

         2. ARP链路状态监控

               1. active-backup工作模式下的ARP链路状态监控

   该模式下的ARP链路状态监控可以分为两个阶段:

   如果当前活动网卡(curr_active_slave不为NULL)存在,则以间隔 arp_interval毫秒从当前活动网卡向arp_targets表示的各个IP地址发送ARP请求,如果当前活动网卡在过去的2*arp_interval毫秒内没有数据包发送*和*接收并且已经作为活动网卡至少 2*arp_interval毫秒,则把当前活动网卡的链路状态设置为BOND_LINK_DOWN并且试图在链路状态为BOND_LINK_UP或者BOND_LINK_BACK的网卡中选取一个网卡作为当前活动网卡。如果有这样一个网卡存在,则原来的活动网卡的活动状态被设置为BOND_STATE_BACKUP,并且IFF_NOARP标志被设置,新的活动网卡链路状态被设置为BOND_STATE_UP, 活动状态被设置为BOND_STATE_ACTIVE,IFF_NOARP标志被清除。

   如果上述过程没有选出新的活动网卡(正常情况下active-backup 模式下除当前活动网卡外所有网卡的链路状态都是BOND_LINK_DOWN,所以可能没有链路状态为BOND_LINK_UP或者BOND_LINK_BACK的后备网卡),则开始一个下述的选取活动网卡的过程:

   从第一块可用(即IFF_UP标志被设置,netif_running(dev)和netif_carrier_ok(dev)都返回非0值)物理网卡开始,向arp_targets表示的各个IP地址发送ARP请求,然后观察所有的物理网卡,如果有物理网卡在arp_interval毫秒内有数据发送*和*接收,就把它设置为当前活动网卡,结束这个选取过程。否则换下一个可用物理网卡,重复这个过程。

   注意即使物理网卡被设置IFF_NOARP标志,仍旧可以收到ARP应答数据包。

               2. 其他工作模式下的ARP链路状态监控

   虚拟网卡每arp_interval遍历一遍所有被绑定物理网卡,如果在网卡在过去的2 * arp_interval毫秒内没有任何数据的发送*或者*接收,就把网卡的链路状态设置为 BOND_LINK_DOWN,活动状态设置为BOND_STATE_BACKUP,如果在过去的arp_interval毫秒有数据包发送*和*接收,则把网卡的链路状态设置为BOND_LINK_UP,活动状态设置为 BOND_STATE_ACTIVE。

   在遍历过程中,对每一个可用的物理网卡(IFF_UP标志被设置,netif_running(dev)和netif_carrier_ok(dev)都返回非0值),都试图从该网卡向arp_targets表示的各个IP地址发送ARP请求,保证其他的被绑定的物理网卡可以收到ARP应答包。


|
好帖就顶。

|
虽然看不太懂,还是要顶一下

    
 
 

您可能感兴趣的文章:

  • 【百度分享】Socket通讯模块压力及大数据对比工具开发之aperlib(二)
  • 【百度分享】Socket通讯模块压力及大数据对比工具开发之aperlib(八)
  • python发布模块的步骤分享
  • 【百度分享】Socket通讯模块压力及大数据对比工具开发之aperlib(三)
  • 【百度分享】Socket通讯模块压力及大数据对比工具开发之aperlib(七)
  • 【百度分享】Socket通讯模块压力及大数据对比工具开发之aperlib(一)
  • 【百度分享】基于内核模块的测试代码编写(一)
  • ubuntu12.04使用c编写php扩展模块教程分享
  • 【百度分享】基于内核模块的测试代码编写(三)
  • [百度分享]Bonding模块主要工作模式相关代码分析(一)
  • 用smtplib和email封装python发送邮件模块类分享
  • 【百度分享】基于内核模块的测试代码编写(二)
  • [百度分享]Bonding模块工作流程综述
  • [百度分享]Bonding 模块代码及主要工作模式分析(4)
  • [百度分享]Bonding 模块代码及主要工作模式分析(2)
  • 『分享』从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响!!! (转载)
  • [百度分享]Bonding 模块代码及主要工作模式分析(3)
  • [百度分享]Bonding模块主要工作模式相关代码分析(二)
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • java单例模式4种使用方式分享
  • PHP中数据库单例模式的实现代码分享
  • 简单的观察者模式示例分享
  • java设计模式之实现对象池模式示例分享
  • 线程安全的单例模式的几种实现方法分享
  • c#使用简单工厂模式实现生成html文件的封装类分享
  • 浅析MVP模式中V-P交互问题及案例分享
  • ​docker之轻量虚拟化技术——docker实战分享
  • php利用腾讯ip分享计划获取地理位置示例分享
  • 点对点文件分享客户端 PeerProject
  • 网络文件分享 Giver
  • IM及文件分享软件 iptux
  • P2P分享软件 Alliance P2P
  • 文件分享软件 eMule Plus
  • P2P 文件分享软件 ShakesPeer
  • 分享页面内容插件 ContentShare
  • 社交分享按钮生成JS库 Socialite.js
  • P2P分享软件 Phex
  • 前端代码编辑和分享平台 RunJS
  • jQuery 分享按钮插件 Share Button
  • 昨天考过SCJP快乐大家分享
  • P2P文件分享 GNUnet
  • 响应式社交分享按钮 RRSSB
  • 谁有免费的英文Office2003(日文也成)分享一下吧!
  • 谁有qmail的日常维护,日志分析的资料分享下?
  • 代码分享
  • 谁有xml和libxml2的说明文档,分享一下吧
  • Java代码分享工具 Java Gems


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3