当前位置: 技术问答>linux和unix
[百度分享]Bonding 模块代码及主要工作模式分析(4)
来源: 互联网 发布时间:2016-08-29
本文导语: * bond_check_dev_link 原型: static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_dev, int reporting) 该函数调用MII/ETHTOOL IOCTL或者使用netif_carrier_ok()检查链路是否正常工作(如果用户指定了use_carrier...
* bond_check_dev_link
原型:
static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_dev, int reporting)
该函数调用MII/ETHTOOL IOCTL或者使用netif_carrier_ok()检查链路是否正常工作(如果用户指定了use_carrier)参数,如果该函数返回BMSR_LSTATUS表明链路是正常的,否则表示链路故障(例如掉网线等等)。
2. ARP链路状态监控
* bond_loadbalance_arp_mon
原型:
static void bond_loadbalance_arp_mon(struct net_device *bond_dev)
如果虚拟网卡工作在*非*BOND_MODE_ACTIVEBACKUP 模式下,而用户指定了使用ARP状态监控,则周期性地对每一个被绑定物理网卡调用该函数,注意该函数不使用 downdelay和updelay参数。
由于*非*BOND_MODE_ACTIVEBACKUP模式下所有的被绑定网卡都是处于活动状态(BOND_STATE_ACTIVE),所以该函数的功能是轮流从每一个被绑定物理网卡发送ARP请求,并且在一段时间间隔内是否有数据包接收,如果没有就设置被检查物理网卡的链路状态为BOND_LINK_DOWN,活动状态设置为BOND_STATE_BACKUP 表示不参与发送数据(但是只要IFF_UP被设置、netif_running和netif_carrier_ok都返回非0(真)值,即本地网卡检查通过,仍然周期性地发送ARP请求出去),请参考5.2节中的描述。
该函数主要做如下操作:
1. 计算局部变量delta_in_ticks = (bond->params.arp_interval * HZ) / 1000,即arp_interval参数的jiffies表示。
2. 如果kill_timers被设置,直接退出。
3. 如果没有任何物理网卡被绑定,重新设置定时器,退出。
4. 枚举所有被绑定的物理网卡,做如下操作:
1. 假如物理网卡的链路状态不是BOND_LINK_UP并且在delta_in_ticks时间间隔内发送过*并且*接受过数据包,则把链路状态设置为BOND_LINK_UP,活动状态设置为BOND_STATE_ACTIVE,并且如果curr_active_slave为空则设置do_failover局部变量。
2. 假如物理网卡的链路状态是BOND_LINK_UP并且在2*delta_in_ticks时间间隔内没有发送过或者没有接受过数据包,则把链路状态设置为BOND_LINK_DOWN,活动状态设置为BOND_STATE_BACKUP,如果当前slave是curr_active_slave则设置do_failover局部变量。
3. 如果dev->flags中IFF_UP被设置,netif_running和netif_carrier_ok都返回非0(真)值,则尝试调用bond_arp_send_all从该网卡发送ARP请求(参考bond_arp_send_all的描述)。
5. 如果do_failover被设置,调用bond_select_active_slave。
6. 设置定时器的超时值为jiffies+delta_in_ticks。
* bond_activebackup_arp_mon
原型:
static void bond_activebackup_arp_mon(struct net_device *bond_dev)
如果虚拟网卡工作在BOND_MODE_ACTIVEBACKUP模式下,而用户指定了使用ARP状态监控,则周期性地对每一个被绑定物理网卡调用该函数。
该函数主要做如下操作:
1. 计算局部变量delta_in_ticks = (bond->params.arp_interval * HZ) / 1000,即arp_interval参数的jiffies表示。
2. 如果kill_timers被设置,直接退出。
3. 如果没有任何物理网卡被绑定,重新设置定时器,退出。
4. 枚举所有被绑定的物理网卡,做如下操作:
1. 如果物理网卡在时间间隔delta_in_ticks内接收过数据包,就把网卡的链路状态设置为BOND_LINK_UP(网卡的活动状态保持不变),设置curr_active_slave为NULL。
2. 如果物理网卡在时间间隔3*delta_in_ticks内没有接收过数据包并且该网卡不是curr_active_slave,就把网卡的链路状态设置为BOND_LINK_DOWN并且调用bond_set_slave_inactive_flags设置网卡的活动状态为BOND_STATE_BACKUP,并且设置IFF_NOARP标志位,设置curr_active_slave为NULL。
5. 检查curr_active_slave,如果curr_active_slave不为NULL:
1. 如果curr_active_slave在2*delta_in_ticks内没有发送也没有接收过数据包,就把curr_active_slave的链路状态设置为BOND_LINK_DOWN并且调用bond_select_active_slave寻找一个新的网卡作为新的curr_active_slave,设置current_arp_slave为curr_active_slave。
2. 如果使用bond->primary_slave并且bond->primary_slave的链路状态是BOND_LINK_UP且bond->primary_slave不是curr_active_slave,就把bond->primary_slave作为新的curr_active_slave。
3. 否则设置current_arp_slave为NULL;
4. 调用bond_arp_send_all通过curr_active_slave发送ARP请求。
6. 检查curr_active_slave,如果curr_active_slave为NULL,则从current_arp_slave 开始或者从first_slave开始选出一个网卡并且把链路状态设置为BOND_LINK_BACK的作为 curr_active_slave的候选者(包存在current_arp_slave中),在下一次lbond_activebackup_arp_mon 被调用的时候将把这个网卡设置为curr_active_slave。
7. 设置定时器的超时值为jiffies+delta_in_ticks。
3. slave切换
* bond_find_best_slave
原型:
static struct slave *bond_find_best_slave(struct bonding *bond)
该函数从被绑定网卡中选出最佳者作为curr_active_slave的候选,主要做如下操作:
1. 如果没有物理网卡被绑定,返回NULL。
2. 如果没有设置primary_slave或者primary_slave不可用,从first_slave开始,否则从primary_slave开始遍历被绑定物理网卡列表,如果有网卡的链路状态为BOND_LINK_UP,则返回这个物理网卡。如果没有链路状态为BOND_LINK_UP的网卡,返回处于BOND_LINK_BACK状态最久者(delay值最小)。
* bond_change_active_slave
原型:
static void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
该函数切换new_active为新的curr_active_slave,主要做如下操作:
1. 如果curr_active_slave和new_active相同,不做任何操作。
2. 如果new_active的链路状态是BOND_LINK_BACK,把链路状态设为BOND_LINK_UP。
3. 如果当前工作在BOND_MODE_ACTIVEBACKUP状态,把curr_active_slave的活动状态设置为BOND_STATE_BACKUP,并且设置IFF_NOARP标志位;把new_active的活动状态设置为BOND_STATE_ACTIVE,清除IFF_NOARP标志位。
4. 设置curr_active_slave为new_active。
6. 参考
[1]《Linux 多网卡绑定/负载均衡调研报告》
[2]《Linux Ethernet Bonding Driver mini-howto》/src/net/Documentation/networking/bonding.txt
[3]《The Linux® Networking Architecture: Design and Implementation of Network Protocols in the Linux Kernel》Klaus Wehrle
[4]《Understanding Linux Network_Internals》Christian Benvenuti
原型:
static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_dev, int reporting)
该函数调用MII/ETHTOOL IOCTL或者使用netif_carrier_ok()检查链路是否正常工作(如果用户指定了use_carrier)参数,如果该函数返回BMSR_LSTATUS表明链路是正常的,否则表示链路故障(例如掉网线等等)。
2. ARP链路状态监控
* bond_loadbalance_arp_mon
原型:
static void bond_loadbalance_arp_mon(struct net_device *bond_dev)
如果虚拟网卡工作在*非*BOND_MODE_ACTIVEBACKUP 模式下,而用户指定了使用ARP状态监控,则周期性地对每一个被绑定物理网卡调用该函数,注意该函数不使用 downdelay和updelay参数。
由于*非*BOND_MODE_ACTIVEBACKUP模式下所有的被绑定网卡都是处于活动状态(BOND_STATE_ACTIVE),所以该函数的功能是轮流从每一个被绑定物理网卡发送ARP请求,并且在一段时间间隔内是否有数据包接收,如果没有就设置被检查物理网卡的链路状态为BOND_LINK_DOWN,活动状态设置为BOND_STATE_BACKUP 表示不参与发送数据(但是只要IFF_UP被设置、netif_running和netif_carrier_ok都返回非0(真)值,即本地网卡检查通过,仍然周期性地发送ARP请求出去),请参考5.2节中的描述。
该函数主要做如下操作:
1. 计算局部变量delta_in_ticks = (bond->params.arp_interval * HZ) / 1000,即arp_interval参数的jiffies表示。
2. 如果kill_timers被设置,直接退出。
3. 如果没有任何物理网卡被绑定,重新设置定时器,退出。
4. 枚举所有被绑定的物理网卡,做如下操作:
1. 假如物理网卡的链路状态不是BOND_LINK_UP并且在delta_in_ticks时间间隔内发送过*并且*接受过数据包,则把链路状态设置为BOND_LINK_UP,活动状态设置为BOND_STATE_ACTIVE,并且如果curr_active_slave为空则设置do_failover局部变量。
2. 假如物理网卡的链路状态是BOND_LINK_UP并且在2*delta_in_ticks时间间隔内没有发送过或者没有接受过数据包,则把链路状态设置为BOND_LINK_DOWN,活动状态设置为BOND_STATE_BACKUP,如果当前slave是curr_active_slave则设置do_failover局部变量。
3. 如果dev->flags中IFF_UP被设置,netif_running和netif_carrier_ok都返回非0(真)值,则尝试调用bond_arp_send_all从该网卡发送ARP请求(参考bond_arp_send_all的描述)。
5. 如果do_failover被设置,调用bond_select_active_slave。
6. 设置定时器的超时值为jiffies+delta_in_ticks。
* bond_activebackup_arp_mon
原型:
static void bond_activebackup_arp_mon(struct net_device *bond_dev)
如果虚拟网卡工作在BOND_MODE_ACTIVEBACKUP模式下,而用户指定了使用ARP状态监控,则周期性地对每一个被绑定物理网卡调用该函数。
该函数主要做如下操作:
1. 计算局部变量delta_in_ticks = (bond->params.arp_interval * HZ) / 1000,即arp_interval参数的jiffies表示。
2. 如果kill_timers被设置,直接退出。
3. 如果没有任何物理网卡被绑定,重新设置定时器,退出。
4. 枚举所有被绑定的物理网卡,做如下操作:
1. 如果物理网卡在时间间隔delta_in_ticks内接收过数据包,就把网卡的链路状态设置为BOND_LINK_UP(网卡的活动状态保持不变),设置curr_active_slave为NULL。
2. 如果物理网卡在时间间隔3*delta_in_ticks内没有接收过数据包并且该网卡不是curr_active_slave,就把网卡的链路状态设置为BOND_LINK_DOWN并且调用bond_set_slave_inactive_flags设置网卡的活动状态为BOND_STATE_BACKUP,并且设置IFF_NOARP标志位,设置curr_active_slave为NULL。
5. 检查curr_active_slave,如果curr_active_slave不为NULL:
1. 如果curr_active_slave在2*delta_in_ticks内没有发送也没有接收过数据包,就把curr_active_slave的链路状态设置为BOND_LINK_DOWN并且调用bond_select_active_slave寻找一个新的网卡作为新的curr_active_slave,设置current_arp_slave为curr_active_slave。
2. 如果使用bond->primary_slave并且bond->primary_slave的链路状态是BOND_LINK_UP且bond->primary_slave不是curr_active_slave,就把bond->primary_slave作为新的curr_active_slave。
3. 否则设置current_arp_slave为NULL;
4. 调用bond_arp_send_all通过curr_active_slave发送ARP请求。
6. 检查curr_active_slave,如果curr_active_slave为NULL,则从current_arp_slave 开始或者从first_slave开始选出一个网卡并且把链路状态设置为BOND_LINK_BACK的作为 curr_active_slave的候选者(包存在current_arp_slave中),在下一次lbond_activebackup_arp_mon 被调用的时候将把这个网卡设置为curr_active_slave。
7. 设置定时器的超时值为jiffies+delta_in_ticks。
3. slave切换
* bond_find_best_slave
原型:
static struct slave *bond_find_best_slave(struct bonding *bond)
该函数从被绑定网卡中选出最佳者作为curr_active_slave的候选,主要做如下操作:
1. 如果没有物理网卡被绑定,返回NULL。
2. 如果没有设置primary_slave或者primary_slave不可用,从first_slave开始,否则从primary_slave开始遍历被绑定物理网卡列表,如果有网卡的链路状态为BOND_LINK_UP,则返回这个物理网卡。如果没有链路状态为BOND_LINK_UP的网卡,返回处于BOND_LINK_BACK状态最久者(delay值最小)。
* bond_change_active_slave
原型:
static void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
该函数切换new_active为新的curr_active_slave,主要做如下操作:
1. 如果curr_active_slave和new_active相同,不做任何操作。
2. 如果new_active的链路状态是BOND_LINK_BACK,把链路状态设为BOND_LINK_UP。
3. 如果当前工作在BOND_MODE_ACTIVEBACKUP状态,把curr_active_slave的活动状态设置为BOND_STATE_BACKUP,并且设置IFF_NOARP标志位;把new_active的活动状态设置为BOND_STATE_ACTIVE,清除IFF_NOARP标志位。
4. 设置curr_active_slave为new_active。
6. 参考
[1]《Linux 多网卡绑定/负载均衡调研报告》
[2]《Linux Ethernet Bonding Driver mini-howto》/src/net/Documentation/networking/bonding.txt
[3]《The Linux® Networking Architecture: Design and Implementation of Network Protocols in the Linux Kernel》Klaus Wehrle
[4]《Understanding Linux Network_Internals》Christian Benvenuti
|
很好,继续收藏。
|
好帖就顶。百度名人!