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

[百度分享]Bonding模块主要工作模式相关代码分析(二)

    来源: 互联网  发布时间:2016-09-18

    本文导语:  现在介绍下关键函数: 模块初始化/释放 初始化 bonding_init 原型: static int __init bonding_init(void) bonding_init作为bonging模块的初始化函数,在模块被加载时被调用。它主要做如下工作: 1. 调用函数bond_check_params解析传...

现在介绍下关键函数:
模块初始化/释放
初始化
bonding_init
原型:
static int __init bonding_init(void)
bonding_init作为bonging模块的初始化函数,在模块被加载时被调用。它主要做如下工作:
1. 调用函数bond_check_params解析传入模块的参数并检查其合法性,结果放入数据结构params中。其中params是一个类型为bond_params的全局变量。
2. 如果内核支持proc文件系统,调用bond_create_proc_dir在/proc/net下创建目录/proc/net/bonding。
3. 如果传入参数指定了bond设备的个数(通过参数max_bonds
4. 调用register_netdevice_notifier,注册函数bond_netdev_notifier为网络事件处理函数。
 bond_init
原型:
static int __init bond_init(struct net_device *bond_dev, struct bond_params *params)
该函数对每一个新创建的虚拟网络设备调用一次。它主要做下列工作。
1. 取出虚拟网络设备bond_dev的私有数据块,用bond指向它(struct bonding *bond)。
2. 初始化两个读写锁bond->lock和bond->curr_slave_lock。
3. 把bond->first_slave、bond->curr_active_slave、bond->current_arp_slave、bond->primary_slave全部置为NULL。bond->dev指向属主网络设备bond_dev。
4. 设置bond_dev的一系列通用接口函数,例如open、close、get_stats、do_ioctl、set_multicast_list、change_mtu和set_mac_address。
5. 根据不同的工作模式,设置bond_dev的通用接口函数hard_start_xmit指向不同的目的函数。例如如果工作模式是BOND_MODE_ROUNDROBIN,则 hard_start_xmit指向函数bond_xmit_roundrobin。
6. 设置bond_dev->tx_queue_len为0,表示发送队列大小没有限制。
7. 设置bond_dev->flags为IFF_MASTER|IFF_MULTICAST表示该设备支持Muticase并且是一个流量均衡组中的master(被它管辖的其他物理网卡将被设置IFF_SLAVE标志)。
8. 其他和VLAN相关的标志设置和初始化。
9. 如果内核支持proc文件系统,调用bond_create_proc_entry在目录/proc/net/bonding下创建对应的proc文件。
10. 调用list_add_tail把该bonding数据结构添加到bond_dev_list中。

释放
 bonding_exit
原型:
static void __exit bonding_exit(void)
该函数在模块被卸载的时候被调用,它主要做如下工作:
1. 调用unregister_netdevice_notifier注销网络事件处理函数。
2. 调用bond_free_all注销所有形如bondN的虚拟网络接口。bond_free_all遍历bond_dev_list链表,并且对其中的每一个类型为struct bonding*的数据结构bond做如下操作:
a) 调用unregister_netdevice注销bond->dev
b) 调用bond_deinit(bond->dev)
3. 调用bond_destroy_proc_dir删除/proc/net/bonding目录
 bond_deinit
原型:
static inline void bond_deinit(struct net_device *bond_dev)
该函数对每一个虚拟网卡的实例调用一次,它主要做如下操作:
1. 调用list_del把虚拟网卡对应的bonding数据结构从bond_dev_list链表中摘除。
2. 调用bond_remove_proc_entry删除/proc/net/bonding目录中的对应文件。


物理网卡的绑定/解除绑定
      在下面的讨论中,假定ifenslave使用新的ABI接口,即:
    在绑定物理网卡时,如果虚拟的网卡还没有MAC地址,则ifenslave通过IOCTL把该虚拟网卡的MAC地址设置为该物理网卡的MAC地址(保证bond_enslave被调用时虚拟网卡已经有了MAC地址)。
 如果被绑定网卡处于UP状态,则ifenslave首先把它设置为DOWN状态(保证bond_enslave被调用时被绑定物理网卡处于DOWN状态)。
如果使用旧版本的ABI接口,则虚拟的网卡的MAC地址由bonding模块在bond_enslave函数中自行设置,并且被绑定网卡在bond_enslave被调用时可能处于UP状态,需要由bond_enslave函数自行处理。
绑定
bond_enslave
原型:
static int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
该函数在试图把一个物理网卡绑定到一个虚拟的网卡时被调用,其中bond_dev表示虚拟的网卡,slave_dev表示真实的物理网卡。该函数主要做如下操作:
1. 取出bond_dev的私有数据,用bond指向它(struct bonding *)。
2. 一系列的合法性检查3. 调用kmalloc分配一个新的slave结构。
4. 把slave_dev->flags保存在slave->original_flags中。
5. 把slave_dev原有的MAC地址保存在slave-> perm_hwaddr中。
6. 设置slave_dev新的MAC地址为虚拟网卡的MAC地址。
7. 调用netdev_set_master设置slave_dev
8. 设置slave->dev指向slave_dev。
9. 如果bond_dev工作在模式BOND_MODE_TLB或者BOND_MODE_ALB,对slave调用bond_alb_init_slave函数。
10. 维护和Multicast以及VLAN相关的一系列数据结构。
11. 调用bond_attach_slave把slave加入bond的链表(通过维护bond-> first_slave和slave结构的next,prev指针)
12. 把slave的delay和link_failure_count都清零。
13. 监测slave_dev的链路状态:
14. 调用bond_update_speed_duplex更新slave_dev的链路速率,如果失败则设置slave_dev的链路速率为100M全双工。
15. 如果虚拟网卡工作在BOND_MODE_ACTIVEBACKUP、BOND_MODE_TLB或者BOND_MODE_ALB模式下,并且slave_dev是用户指定的主网卡,则设置bond->primary_slave为slave_dev。
16. 设置bond->curr_active_slave和slave的活动状态,维护VLAN和Multicast相关数据结构
解除绑定
 bond_release
原型
static int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
该函数在试图解除一个物理网卡的绑定状态时被调用,其中bond_dev表示虚拟的网卡,slave_dev表示真实的物理网卡。该函数主要做如下操作:
1. 取出bond_dev的私有数据,用bond指向它(struct bonding *)。
2. 寻找对应的slave结构。
3. 一系列的合法性检查
4. 如果虚拟网卡工作在BOND_MODE_8023AD模式,调用bond_3ad_unbind_slave
5. 调用bond_detach_slave把slave从bond的链表中摘除(通过维护bond-> first_slave和slave结构的next,prev指针)。
6. 如果slave_dev是虚拟网卡以前的主物理网卡,则设置bond->primary_slave为NULL。
7. 如果slave_dev是虚拟网卡以前的活动网卡,则设置bond->active_slave为NULL(通过调用bond_change_active_slave函数)。
8. 如果虚拟网卡工作在模式BOND_MODE_TLB或者BOND_MODE_ALB则调用bond_alb_deinit_slave。
9. 如果slave_dev是虚拟网卡以前的活动网卡,则调用bond_select_active_slave寻找一个新的活动网卡。
10. 如果虚拟网卡再也没有管辖的物理网卡,清除虚拟网卡的MAC地址(如果新调用ifenslave绑定物理网卡,则重新设置这个MAC地址)。
11. 维护VLAN和Multicast相关的数据结构。
12. 调用netdev_set_master解除master和slave的绑定关系并且调用dev_close关闭slave_dev。
13. 恢复slave_dev的MAC地址(根据slave->perm_hwaddr)和flags(根据slave->original_flags)。
14. 调用kfree释放slave结构。

网卡驱动通用接口(interface service routines)
既然bonding模块本质上是一个虚拟网卡的驱动模块,所以必须提供一组所有网卡驱动模块都遵守的通用接口函数。ioctl接口
bond_do_ioctl(net_device->do_ioctl接口)
原型:
static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd)
该函数是虚拟网卡的IOCTRL接口,仅仅根据不同的IOCTRL命令调用其他函数执行相应的功能,所以不再列出操作流程而仅仅列举出这些被调用的函数和相应的功能:
 链路状态设置和查询(bond_ethtool_ioctl或者if_mii)
 Bonding模块状态查询(bond_info_query)
 被绑定的物理网卡状态查询(bond_slave_info_query)
 物理网卡的绑定和解除绑定(bond_enslave/bond_release)
 虚拟网卡的MAC地址设置(bond_sethwaddr)
 切换当前活动的物理网卡(bond_ioctl_change_active)
统计值查询
 bond_get_stats(net_device-> get_stats接口)
原型:
static struct net_device_stats *bond_get_stats(struct net_device *bond_dev)


链路状态监控
MII链路状态监控
 bond_mii_monitor
原型:
static void bond_mii_monitor(struct net_device *bond_dev)
如果使用MII链路状态监控,则该函数被周期调用以检测每一个被绑定物理网卡的链路状态, 主要做如下操作:
1. 计算局部变量delta_in_ticks = (bond->params.miimon * HZ) / 1000,即miimon参数的jiffies表示。
2. 如果kill_timers被设置,直接退出。
3. 如果没有任何物理网卡被绑定,重新设置定时器,退出。
4. 根据bond_check_dev_link的结果,按照第5节描述的MII链路状态监控模型设置网卡的链路状态。
5. 如果原来物理网卡的链路状态为BOND_LINK_FAIL,而bond_check_dev_link返回非BMSR_LSTATUS值,则除了把链路状态设置为BOND_LINK_DOWN之外,还做如下操作:
a) 如果虚拟网卡工作在模式BOND_MODE_8023AD,调用bond_3ad_handle_link_change
b) 如果虚拟网卡工作在模式BOND_MODE_TLB或者BOND_MODE_ALB模式下,调用bond_alb_handle_link_change。
c) 如果当前被检查的slave不是curr_active_slave,设置标志do_failover表明可能会发生slave切换。
6. 如果原来物理网卡的链路状态为BOND_LINK_BACK而bond_check_dev_link返回BMSR_LSTATUS,则除了把链路状态设置为BOND_LINK_UP之外,还做如下操作:
a) 如果虚拟网卡工作在模式BOND_MODE_8023AD或者被监测网卡不是primary_slave,则设置物理网卡的活动状态为BOND_STATE_BACKUP
b) 如果虚拟网卡*不是*工作在模式BOND_MODE_ACTIVEBACKUP,则设置物理网卡的活动状态为BOND_STATE_ACTIVE
c) 如果虚拟网卡工作在模式BOND_MODE_8023AD,调用bond_3ad_handle_link_change
d) 如果虚拟网卡工作在模式BOND_MODE_TLB或者BOND_MODE_ALB模式下,调用bond_alb_handle_link_change。
e) 如果当前被检查的slave不是curr_active_slave,设置标志do_failover表明可能会发生slave切换。
7. 调用bond_update_speed_duplex更新物理网卡的速率。
8. 如果do_failover被设置,调用bond_select_active_slave。
9. 设置定时器的超时值为jiffies+delta_in_ticks。
 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表明链路是正常的,否则表示链路故障(例如掉网线等等)。
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. 枚举所有被绑定的物理网卡
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. 枚举所有被绑定的物理网卡
5. 检查curr_active_slave,如果curr_active_slave不为NULL:
a) 如果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。
b) 如果使用bond->primary_slave并且bond->primary_slave的链路状态是BOND_LINK_UP且bond->primary_slave不是curr_active_slave,就把bond->primary_slave作为新的curr_active_slave。
c) 否则设置current_arp_slave为NULL;
d) 调用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中),在下一次bond_activebackup_arp_mon被调用的时候将把这个网卡设置为curr_active_slave。
7. 设置定时器的超时值为jiffies+delta_in_ticks。

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。

|
怎么有乱码

|
怎么有乱码

|
???
no

|
收藏,学习!

    
 
 

您可能感兴趣的文章:

  • 【百度分享】Socket通讯模块压力及大数据对比工具开发之aperlib(二)
  • 【百度分享】Socket通讯模块压力及大数据对比工具开发之aperlib(八)
  • python发布模块的步骤分享
  • 【百度分享】Socket通讯模块压力及大数据对比工具开发之aperlib(三)
  • 【百度分享】Socket通讯模块压力及大数据对比工具开发之aperlib(七)
  • 【百度分享】Socket通讯模块压力及大数据对比工具开发之aperlib(一)
  • 【百度分享】基于内核模块的测试代码编写(一)
  • ubuntu12.04使用c编写php扩展模块教程分享
  • 【百度分享】基于内核模块的测试代码编写(三)
  • [百度分享]Bonding模块主要工作模式相关代码分析(一)
  • 用smtplib和email封装python发送邮件模块类分享
  • 【百度分享】基于内核模块的测试代码编写(二)
  • [百度分享]Bonding模块工作流程综述
  • [百度分享]Bonding 模块代码及主要工作模式分析(4)
  • [百度分享]Bonding 模块代码及主要工作模式分析(1)
  • [百度分享]Bonding 模块代码及主要工作模式分析(2)
  • 『分享』从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响!!! (转载)
  • [百度分享]Bonding 模块代码及主要工作模式分析(3)
  •  
    本站(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